split suspension and steering
This commit is contained in:
parent
cfe8a0acbd
commit
884dc14c9f
2 changed files with 65 additions and 37 deletions
11
src/bike.rs
11
src/bike.rs
|
@ -26,9 +26,16 @@ pub enum CyberWheel {
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct WheelState {
|
pub struct WheelState {
|
||||||
pub displacement: Scalar,
|
pub displacement: Scalar,
|
||||||
|
pub force_normal: Scalar,
|
||||||
pub sliding: bool,
|
pub sliding: bool,
|
||||||
pub grounded: bool,
|
pub contact_point: Option<Vec3>,
|
||||||
pub ppos: Vec3,
|
pub contact_normal: Option<Vec3>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WheelState {
|
||||||
|
pub fn reset(&mut self) {
|
||||||
|
*self = Self::default();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy, Debug, Reflect)]
|
#[derive(Component, Clone, Copy, Debug, Reflect)]
|
||||||
|
|
|
@ -163,26 +163,15 @@ mod systems {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn suspension(
|
pub(super) fn suspension(
|
||||||
mut bike_body_query: Query<
|
mut bike_body_query: Query<(&Transform, &mut ExternalForce), With<CyberBikeBody>>,
|
||||||
(&Transform, &mut ExternalForce, RigidBodyQuery),
|
|
||||||
With<CyberBikeBody>,
|
|
||||||
>,
|
|
||||||
mut wheel_mesh_query: Query<
|
mut wheel_mesh_query: Query<
|
||||||
(&mut Transform, &mut WheelState, &WheelConfig, &CyberWheel),
|
(&mut Transform, &mut WheelState, &WheelConfig, &CyberWheel),
|
||||||
Without<CyberBikeBody>,
|
Without<CyberBikeBody>,
|
||||||
>,
|
>,
|
||||||
caster_query: Query<(&RayCaster, &RayHits, &CyberWheel)>,
|
caster_query: Query<(&RayCaster, &RayHits, &CyberWheel)>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
input: Res<InputState>,
|
|
||||||
mut gizmos: Gizmos,
|
mut gizmos: Gizmos,
|
||||||
) {
|
) {
|
||||||
let max_thrust = 100.0;
|
|
||||||
let max_yaw = 50.0;
|
|
||||||
let mut thrust = input.throttle * max_thrust;
|
|
||||||
if input.brake {
|
|
||||||
thrust *= -1.0;
|
|
||||||
}
|
|
||||||
let yaw = input.yaw * max_yaw;
|
|
||||||
let dt = time.delta().as_secs_f32();
|
let dt = time.delta().as_secs_f32();
|
||||||
|
|
||||||
let mut front_caster = &RayCaster::default();
|
let mut front_caster = &RayCaster::default();
|
||||||
|
@ -204,10 +193,7 @@ mod systems {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let Ok((bike_xform, mut bike_forces, rbq)) = bike_body_query.get_single_mut() else {
|
let (bike_xform, mut bike_forces) = bike_body_query.single_mut();
|
||||||
bevy::log::warn!("Couldn't get body query");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
for (mut xform, mut state, config, wheel) in wheel_mesh_query.iter_mut() {
|
for (mut xform, mut state, config, wheel) in wheel_mesh_query.iter_mut() {
|
||||||
let (caster, hits) = match wheel {
|
let (caster, hits) = match wheel {
|
||||||
|
@ -217,48 +203,83 @@ mod systems {
|
||||||
|
|
||||||
if let Some(hit) = hits.iter().next() {
|
if let Some(hit) = hits.iter().next() {
|
||||||
let dist = hit.distance;
|
let dist = hit.distance;
|
||||||
let cdir = caster.direction.as_vec3();
|
let hit_point = caster.global_origin() + caster.global_direction() * dist;
|
||||||
xform.translation = config.attach + (cdir * (dist - WHEEL_RADIUS));
|
|
||||||
|
|
||||||
let displacement = config.rest_dist - dist;
|
let displacement = config.rest_dist - dist;
|
||||||
let damper_vel = (state.displacement - displacement) / dt;
|
let damper_vel = (state.displacement - displacement) / dt;
|
||||||
state.displacement = displacement;
|
|
||||||
|
|
||||||
let mag = config.konstant * displacement - config.damping * damper_vel;
|
let mag = config.konstant * displacement - config.damping * damper_vel;
|
||||||
|
|
||||||
let mag = mag.max(0.0);
|
let mag = mag.max(0.0);
|
||||||
|
|
||||||
let fdir = hit.normal;
|
state.force_normal = mag;
|
||||||
let force = fdir * mag;
|
state.contact_normal = Some(hit.normal);
|
||||||
|
state.contact_point = Some(hit_point);
|
||||||
|
state.displacement = displacement;
|
||||||
|
|
||||||
let hit_point = caster.global_origin() + caster.global_direction() * dist;
|
let cdir = caster.direction.as_vec3();
|
||||||
|
xform.translation = config.attach + (cdir * (dist - WHEEL_RADIUS));
|
||||||
|
|
||||||
|
let force = hit.normal * mag;
|
||||||
gizmos.arrow(
|
gizmos.arrow(
|
||||||
hit_point,
|
hit_point,
|
||||||
hit_point + force,
|
hit_point + force,
|
||||||
Color::linear_rgb(1., 0.5, 0.2),
|
Color::linear_rgb(1., 0.5, 0.2),
|
||||||
);
|
);
|
||||||
|
|
||||||
let _vel = rbq.velocity_at_point(hit_point);
|
|
||||||
//bevy::log::info!("{_vel:?}");
|
|
||||||
|
|
||||||
bike_forces.apply_force_at_point(
|
bike_forces.apply_force_at_point(
|
||||||
force,
|
force,
|
||||||
caster.global_origin(),
|
caster.global_origin(),
|
||||||
bike_xform.translation,
|
bike_xform.translation,
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
xform.translation = config.attach + (caster.direction.as_vec3() * config.rest_dist);
|
||||||
|
state.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let normal = hit.normal;
|
pub(super) fn steering(
|
||||||
|
mut bike_query: Query<
|
||||||
|
(&Transform, &mut ExternalForce, RigidBodyQueryReadOnly),
|
||||||
|
With<CyberBikeBody>,
|
||||||
|
>,
|
||||||
|
mut wheels: Query<(&mut WheelState, &WheelConfig, &CyberWheel)>,
|
||||||
|
time: Res<Time>,
|
||||||
|
input: Res<InputState>,
|
||||||
|
mut gizmos: Gizmos,
|
||||||
|
) {
|
||||||
|
let Ok((bike_xform, mut bike_force, bike_body)) = bike_query.get_single_mut() else {
|
||||||
|
bevy::log::warn!("No entity for bike_query.");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let max_thrust = 100.0;
|
||||||
|
let max_yaw = 50.0;
|
||||||
|
let thrust = input.throttle * max_thrust;
|
||||||
|
let yaw = input.yaw * max_yaw;
|
||||||
|
let dt = time.delta().as_secs_f32();
|
||||||
|
|
||||||
|
for (mut state, config, wheel) in wheels.iter_mut() {
|
||||||
|
if let Some(contact_point) = state.contact_point {
|
||||||
|
let vel = bike_body.velocity_at_point(contact_point);
|
||||||
|
bevy::log::info_once!("vel: {vel:?}");
|
||||||
|
let friction = config.friction;
|
||||||
|
bevy::log::info_once!(friction);
|
||||||
|
// just to shut the linter up about state not needing to be mut
|
||||||
|
state.sliding = true;
|
||||||
|
|
||||||
|
let normal = state.contact_normal.unwrap();
|
||||||
let steering = match wheel {
|
let steering = match wheel {
|
||||||
CyberWheel::Front => normal.cross(*bike_xform.back()) * yaw,
|
CyberWheel::Front => normal.cross(*bike_xform.back()) * yaw,
|
||||||
CyberWheel::Rear => Vec3::ZERO,
|
CyberWheel::Rear => Vec3::ZERO,
|
||||||
//_ => normal.cross(*bike_xform.forward()) * yaw, // Vec3::ZERO,
|
|
||||||
};
|
};
|
||||||
let thrust = normal.cross(*bike_xform.right()) * thrust;
|
let thrust = normal.cross(*bike_xform.right()) * thrust;
|
||||||
let total = (thrust + steering) * dt;
|
let total = (thrust + steering) * dt;
|
||||||
bike_forces.apply_force_at_point(total, hit_point, bike_xform.translation);
|
bike_force.apply_force_at_point(total, contact_point, bike_xform.translation);
|
||||||
gizmos.arrow(hit_point, hit_point + total, Color::linear_rgb(1., 1., 0.2));
|
gizmos.arrow(
|
||||||
} else {
|
contact_point,
|
||||||
xform.translation = config.attach + (caster.direction.as_vec3() * config.rest_dist);
|
contact_point + total,
|
||||||
|
Color::linear_rgb(1., 1., 0.2),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,7 +322,7 @@ mod systems {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
use systems::{apply_lean, calculate_lean, suspension, tweak};
|
use systems::{apply_lean, calculate_lean, steering, suspension, tweak};
|
||||||
|
|
||||||
pub struct CyberPhysicsPlugin;
|
pub struct CyberPhysicsPlugin;
|
||||||
|
|
||||||
|
@ -319,7 +340,7 @@ impl Plugin for CyberPhysicsPlugin {
|
||||||
})
|
})
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedUpdate,
|
FixedUpdate,
|
||||||
(calculate_lean, apply_lean, suspension).chain(),
|
(calculate_lean, apply_lean, suspension, steering).chain(),
|
||||||
)
|
)
|
||||||
.add_systems(Update, tweak);
|
.add_systems(Update, tweak);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue