use colliders for wheels, fields for thrust and steering
This commit is contained in:
parent
94717dd60c
commit
0fae893508
3 changed files with 33 additions and 82 deletions
|
@ -2,17 +2,13 @@ use std::f32::consts::{FRAC_PI_3, FRAC_PI_4};
|
||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::{
|
prelude::{
|
||||||
info, Commands, Entity, Gizmos, Local, Quat, Query, Res, ResMut, Time, Transform, Vec3,
|
info, Gizmos, Local, Quat, Query, Res, ResMut, Time, Transform, Vec3, With, Without,
|
||||||
With, Without,
|
|
||||||
},
|
},
|
||||||
render::color::Color,
|
render::color::Color,
|
||||||
};
|
};
|
||||||
use bevy_rapier3d::{
|
use bevy_rapier3d::prelude::{
|
||||||
dynamics::MassProperties,
|
ExternalForce, QueryFilter, RapierConfiguration, RapierContext, ReadMassProperties,
|
||||||
prelude::{
|
TimestepMode, Velocity,
|
||||||
CollisionGroups, ExternalForce, Group, MultibodyJoint, QueryFilter, RapierConfiguration,
|
|
||||||
RapierContext, ReadMassProperties, TimestepMode, Velocity,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "inspector")]
|
#[cfg(feature = "inspector")]
|
||||||
|
@ -21,7 +17,7 @@ use super::{
|
||||||
CatControllerSettings, CatControllerState, CyberLean, MovementSettings, PreviousVelocity,
|
CatControllerSettings, CatControllerState, CyberLean, MovementSettings, PreviousVelocity,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
bike::{CyberBikeBody, CyberSteering, CyberWheel, WheelConfig, BIKE_WHEEL_COLLISION_GROUP},
|
bike::{CyberBikeBody, CyberSteering, CyberWheel, WheelConfig},
|
||||||
input::InputState,
|
input::InputState,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -138,93 +134,42 @@ pub(super) fn wheel_forces(
|
||||||
(
|
(
|
||||||
&Transform,
|
&Transform,
|
||||||
&Velocity,
|
&Velocity,
|
||||||
&mut PreviousVelocity,
|
|
||||||
&mut ExternalForce,
|
&mut ExternalForce,
|
||||||
Option<&CyberSteering>,
|
Option<&CyberSteering>,
|
||||||
),
|
),
|
||||||
(With<CyberWheel>, Without<CyberBikeBody>),
|
With<CyberWheel>,
|
||||||
>,
|
|
||||||
mut body_query: Query<
|
|
||||||
(
|
|
||||||
&Transform,
|
|
||||||
&Velocity,
|
|
||||||
&mut PreviousVelocity,
|
|
||||||
&ReadMassProperties,
|
|
||||||
),
|
|
||||||
(With<CyberBikeBody>, Without<CyberWheel>),
|
|
||||||
>,
|
>,
|
||||||
wheel_config: Res<WheelConfig>,
|
wheel_config: Res<WheelConfig>,
|
||||||
rapier_config: Res<RapierConfiguration>,
|
|
||||||
context: Res<RapierContext>,
|
context: Res<RapierContext>,
|
||||||
settings: Res<MovementSettings>,
|
settings: Res<MovementSettings>,
|
||||||
input: Res<InputState>,
|
input: Res<InputState>,
|
||||||
mut gizmos: Gizmos,
|
mut gizmos: Gizmos,
|
||||||
) {
|
) {
|
||||||
let (body_xform, body_vel, mut body_pvel, body_mass) = body_query.single_mut();
|
|
||||||
|
|
||||||
let gvec = rapier_config.gravity;
|
|
||||||
|
|
||||||
// body kinematics
|
|
||||||
let body_lin_accel = body_vel.linvel - body_pvel.0.linvel;
|
|
||||||
let body_ang_accel = body_vel.angvel - body_pvel.0.angvel;
|
|
||||||
let mut body_forward = body_vel
|
|
||||||
.linvel
|
|
||||||
.try_normalize()
|
|
||||||
.unwrap_or_else(|| body_xform.forward().normalize());
|
|
||||||
// we're just projecting onto the ground, so nuke the Y.
|
|
||||||
body_forward.y = 0.0;
|
|
||||||
let body_half_mass = body_mass.mass * 0.5;
|
|
||||||
let half_weight = settings.gravity * body_half_mass;
|
|
||||||
|
|
||||||
// wheel stuff
|
// wheel stuff
|
||||||
let radius = wheel_config.radius;
|
let radius = wheel_config.radius;
|
||||||
let squish_radius = 1.5 * radius;
|
|
||||||
|
|
||||||
// inputs
|
// inputs
|
||||||
let steering = input.yaw;
|
let steering = input.yaw;
|
||||||
let throttle = input.throttle * settings.accel;
|
let throttle = input.throttle * settings.accel;
|
||||||
|
|
||||||
for (xform, vel, mut pvel, mut external_force, steering) in wheels_query.iter_mut() {
|
for (xform, velocity, mut external_force, steering) in wheels_query.iter_mut() {
|
||||||
if let Some((_, projected)) =
|
if let Some((_, projected)) =
|
||||||
context.project_point(xform.translation, false, QueryFilter::only_fixed())
|
context.project_point(xform.translation, false, QueryFilter::only_fixed())
|
||||||
{
|
{
|
||||||
//info!("projected point: {:?}", projected);
|
|
||||||
//dbg!("{:?}", projected);
|
|
||||||
let normal = (projected.point - xform.translation);
|
let normal = (projected.point - xform.translation);
|
||||||
let len = normal.length();
|
let len = normal.length();
|
||||||
let normal = normal.normalize();
|
if len < radius {
|
||||||
if len < squish_radius {
|
let mut force = Vec3::ZERO;
|
||||||
let squish = if len > radius {
|
// do thrust's share
|
||||||
1.0 - ((len - radius) / (squish_radius - radius)).powi(2)
|
let thrust = normal.cross(xform.left().into()) * throttle;
|
||||||
} else {
|
force += thrust;
|
||||||
1.0
|
|
||||||
};
|
|
||||||
info!("squish: {squish}");
|
|
||||||
let grav_norm = gvec.normalize().dot(normal);
|
|
||||||
// we're in contact, first gravity
|
|
||||||
let normal = if projected.is_inside { Vec3::Y } else { normal };
|
|
||||||
let mut force = -1.1 * grav_norm * half_weight * normal;
|
|
||||||
|
|
||||||
// do linear acceleration's share
|
// do steering's share
|
||||||
// f = ma
|
|
||||||
let lin_accel_norm = normal.dot(body_lin_accel.normalize());
|
|
||||||
force += body_mass.mass * lin_accel_norm * body_lin_accel;
|
|
||||||
|
|
||||||
// do angular accelerations's share?
|
// do the friction's share
|
||||||
|
|
||||||
// do friction's share (depends on previous three)
|
|
||||||
|
|
||||||
// do thrust's share (depends on friction):
|
|
||||||
//
|
|
||||||
// let ef = ExternalForce::at_point(force, point,
|
|
||||||
// center_of_mass);
|
|
||||||
|
|
||||||
// do steering's share (also depends on friction)
|
|
||||||
|
|
||||||
// apply the squish factor
|
|
||||||
force *= squish;
|
|
||||||
|
|
||||||
// show the force
|
// show the force
|
||||||
|
#[cfg(feature = "inspector")]
|
||||||
gizmos.arrow(xform.translation, force, Color::RED);
|
gizmos.arrow(xform.translation, force, Color::RED);
|
||||||
|
|
||||||
// ok apply the force
|
// ok apply the force
|
||||||
|
@ -233,8 +178,6 @@ pub(super) fn wheel_forces(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body_pvel.0 = *body_vel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// General velocity-based drag-force calculation; does not take orientation
|
/// General velocity-based drag-force calculation; does not take orientation
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rapier3d::{
|
use bevy_rapier3d::{
|
||||||
dynamics::{FixedJointBuilder, Velocity},
|
dynamics::{Ccd, FixedJointBuilder, Velocity},
|
||||||
|
geometry::{Collider, CollisionGroups, Friction},
|
||||||
prelude::{
|
prelude::{
|
||||||
ColliderMassProperties, ExternalForce, MultibodyJoint, PrismaticJointBuilder, RigidBody,
|
ColliderMassProperties, ExternalForce, MultibodyJoint, PrismaticJointBuilder, RigidBody,
|
||||||
Sleeping, TransformInterpolation,
|
Sleeping, TransformInterpolation,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{CyberSteering, CyberWheel, Meshterial, WheelConfig};
|
use super::{CyberSteering, CyberWheel, Meshterial, WheelConfig, BIKE_WHEEL_COLLISION_GROUP};
|
||||||
use crate::action::PreviousVelocity;
|
use crate::action::PreviousVelocity;
|
||||||
|
|
||||||
pub(crate) fn spawn_wheels(
|
pub(crate) fn spawn_wheels(
|
||||||
|
@ -21,10 +22,14 @@ pub(crate) fn spawn_wheels(
|
||||||
let not_sleeping = Sleeping::disabled();
|
let not_sleeping = Sleeping::disabled();
|
||||||
let limits = conf.limits;
|
let limits = conf.limits;
|
||||||
let (meshes, materials) = meshterials;
|
let (meshes, materials) = meshterials;
|
||||||
let rake_vec: Vec3 = Vec3::new(0.0, 1.0, 0.57).normalize(); // about 30 degrees of rake
|
//let rake_vec: Vec3 = Vec3::new(0.0, 1.0, 0.57).normalize(); // about 30
|
||||||
|
// degrees of rake
|
||||||
|
|
||||||
let mut wheel_poses = Vec::with_capacity(2);
|
let mut wheel_poses = Vec::with_capacity(2);
|
||||||
|
|
||||||
|
let (membership, filter) = BIKE_WHEEL_COLLISION_GROUP;
|
||||||
|
let wheels_collision_group = CollisionGroups::new(membership, filter);
|
||||||
|
|
||||||
// front
|
// front
|
||||||
{
|
{
|
||||||
let wheel_x = 0.0;
|
let wheel_x = 0.0;
|
||||||
|
@ -106,6 +111,13 @@ pub(crate) fn spawn_wheels(
|
||||||
SpatialBundle::default(),
|
SpatialBundle::default(),
|
||||||
TransformInterpolation::default(),
|
TransformInterpolation::default(),
|
||||||
RigidBody::Dynamic,
|
RigidBody::Dynamic,
|
||||||
|
Ccd { enabled: true },
|
||||||
|
Friction {
|
||||||
|
coefficient: 0.0,
|
||||||
|
combine_rule: bevy_rapier3d::dynamics::CoefficientCombineRule::Min,
|
||||||
|
},
|
||||||
|
wheels_collision_group,
|
||||||
|
Collider::ball(conf.radius),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,11 +18,7 @@ fn spawn_planet(
|
||||||
|
|
||||||
let (mesh, shape) = gen_planet(2999.9);
|
let (mesh, shape) = gen_planet(2999.9);
|
||||||
|
|
||||||
let pbody = (
|
let pbody = (RigidBody::Fixed, Transform::from_xyz(0.0, 0.1, 0.0));
|
||||||
RigidBody::Fixed,
|
|
||||||
Ccd { enabled: true },
|
|
||||||
Transform::from_xyz(0.0, 0.1, 0.0),
|
|
||||||
);
|
|
||||||
|
|
||||||
let pcollide = (
|
let pcollide = (
|
||||||
shape,
|
shape,
|
||||||
|
@ -32,8 +28,8 @@ fn spawn_planet(
|
||||||
},
|
},
|
||||||
Restitution::new(0.8),
|
Restitution::new(0.8),
|
||||||
Transform::from_xyz(0.0, 1.0, 0.0),
|
Transform::from_xyz(0.0, 1.0, 0.0),
|
||||||
// same as the bike body
|
CollisionGroups::default(), // all colliders
|
||||||
CollisionGroups::new(Group::GROUP_1, Group::GROUP_1),
|
Ccd { enabled: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
commands
|
commands
|
||||||
|
|
Loading…
Reference in a new issue