Builds and runs, but physics is fucked.

This commit is contained in:
Joe Ardent 2022-05-08 10:58:48 -07:00
parent 413ac493df
commit 1579c3d972
9 changed files with 376 additions and 367 deletions

438
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ edition = "2021"
[dependencies] [dependencies]
rand = "0.8" rand = "0.8"
bevy_polyline = "*" bevy_polyline = "0.2"
noise = { git = "https://github.com/Razaekel/noise-rs" } noise = { git = "https://github.com/Razaekel/noise-rs" }
hexasphere = "7" hexasphere = "7"
wgpu = "0.12" wgpu = "0.12"
@ -14,7 +14,7 @@ wgpu = "0.12"
debug_render = [] debug_render = []
[dependencies.bevy] [dependencies.bevy]
version = "0.6" version = "0.7"
default-features = false default-features = false
features = [ features = [
"bevy_gilrs", "bevy_gilrs",
@ -26,11 +26,8 @@ features = [
] ]
[dependencies.bevy_rapier3d] [dependencies.bevy_rapier3d]
#git = "https://github.com/nebkor/bevy_rapier"
#path = "../bevy_rapier/bevy_rapier3d"
#branch = "debug-render-capsule"
features = ["simd-nightly"] features = ["simd-nightly"]
version = "0.12" version = "0.13"
# Maybe also enable only a small amount of optimization for our code: # Maybe also enable only a small amount of optimization for our code:
[profile.dev] [profile.dev]

View File

@ -1,5 +1,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_rapier3d::{na::Vector3, prelude::*}; use bevy_rapier3d::prelude::{
ExternalForce, Friction, NoUserData, RapierConfiguration, RapierPhysicsPlugin, Velocity,
};
use crate::{ use crate::{
bike::{CyberBikeBody, CyberBikeCollider, CyberBikeControl}, bike::{CyberBikeBody, CyberBikeCollider, CyberBikeControl},
@ -28,14 +30,14 @@ fn gravity(
mut config: ResMut<RapierConfiguration>, mut config: ResMut<RapierConfiguration>,
) { ) {
let gravity = xform.single().translation.normalize() * -settings.gravity; let gravity = xform.single().translation.normalize() * -settings.gravity;
config.gravity = gravity.into(); config.gravity = gravity;
} }
fn falling_cat_pid( fn falling_cat_pid(
mut bike_query: Query<( mut bike_query: Query<(
&Transform, &Transform,
&RigidBodyVelocityComponent, &Velocity,
&mut RigidBodyForcesComponent, &mut ExternalForce,
&mut CyberBikeControl, &mut CyberBikeControl,
)>, )>,
) { ) {
@ -105,19 +107,14 @@ fn falling_cat_pid(
} }
} }
forces.torque = torque.into(); forces.torque = torque;
} }
fn drag( fn drag(mut query: Query<(&Velocity, &mut ExternalForce), With<CyberBikeBody>>) {
mut query: Query<
(&RigidBodyVelocityComponent, &mut RigidBodyForcesComponent),
With<CyberBikeBody>,
>,
) {
let (vels, mut forces) = query.single_mut(); let (vels, mut forces) = query.single_mut();
if let Some(vel) = vels.linvel.try_normalize(0.001) { if let Some(vel) = vels.linvel.try_normalize() {
let v2 = vels.linvel.magnitude_squared(); let v2 = vels.linvel.length_squared();
forces.force -= vel * v2 * 0.02; forces.force -= vel * v2 * 0.02;
} }
} }
@ -125,21 +122,21 @@ fn drag(
fn input_forces( fn input_forces(
settings: Res<MovementSettings>, settings: Res<MovementSettings>,
input: Res<InputState>, input: Res<InputState>,
mut cquery: Query<&mut ColliderMaterialComponent, With<CyberBikeCollider>>, mut cquery: Query<&mut Friction, With<CyberBikeCollider>>,
mut bquery: Query<(&Transform, &mut RigidBodyForcesComponent), With<CyberBikeBody>>, mut bquery: Query<(&Transform, &mut ExternalForce), With<CyberBikeBody>>,
) { ) {
let (xform, mut forces) = bquery.single_mut(); let (xform, mut forces) = bquery.single_mut();
let mut cmat = cquery.single_mut(); let mut friction = cquery.single_mut();
// thrust // thrust
let thrust: Vector3<f32> = (xform.forward() * input.throttle * settings.accel).into(); let thrust = xform.forward() * input.throttle * settings.accel;
forces.force += thrust; forces.force += thrust;
// brake // brake
cmat.friction = if input.brake { 2.0 } else { 0.0 }; friction.coefficient = if input.brake { 2.0 } else { 0.0 };
// steering // steering
let torque: Vector3<f32> = (xform.up() * input.yaw * settings.sensitivity).into(); let torque = xform.up() * input.yaw * settings.sensitivity;
forces.torque += torque; forces.torque += torque;
} }

View File

@ -22,65 +22,60 @@ pub struct CyberBikeControl {
pub prev_pitch_error: f32, pub prev_pitch_error: f32,
} }
const BIKE_BODY_GROUP: InteractionGroups = InteractionGroups::new(0b01, 0b01); const BIKE_BODY_COLLISION_GROUP: (u32, u32) = (0b01, 0b01);
const BIKE_WHEEL_GROUP: InteractionGroups = InteractionGroups::new(0b10, 0b10); const BIKE_WHEEL_COLLISION_GROUP: (u32, u32) = (0b10, 0b10);
fn spawn_cyberbike(mut commands: Commands, asset_server: Res<AssetServer>) { fn spawn_cyberbike(mut commands: Commands, asset_server: Res<AssetServer>) {
let xform = Transform::from_translation(Vec3::X * SPAWN_ALTITUDE) let xform = Transform::from_translation(Vec3::X * SPAWN_ALTITUDE)
.with_rotation(Quat::from_axis_angle(Vec3::Z, -89.0f32.to_radians())); .with_rotation(Quat::from_axis_angle(Vec3::Z, -89.0f32.to_radians()));
let mut bbody = RigidBodyBundle::default(); let damping = Damping {
angular_damping: 0.5,
linear_damping: 0.1,
};
let not_sleeping = Sleeping::disabled();
bbody.damping.angular_damping = 0.5; let ccd = Ccd { enabled: true };
bbody.damping.linear_damping = 0.1;
bbody.activation = RigidBodyActivation::cannot_sleep().into();
bbody.ccd = RigidBodyCcd { let bcollider_shape =
ccd_enabled: true, Collider::capsule(Vec3::new(0.0, 0.0, -2.7), Vec3::new(0.0, 0.0, 2.5), 1.0);
ccd_thickness: 0.2,
ccd_max_dist: 2.7,
..Default::default()
}
.into();
let isometry = Isometry::from_parts(xform.translation.into(), xform.rotation.into()); let friction = Friction {
bbody.position = isometry.into(); coefficient: 0.0,
let shape = ColliderShape::capsule(
Vec3::new(0.0, 0.0, -2.7).into(),
Vec3::new(0.0, 0.0, 2.5).into(),
1.0,
);
let bcollide = ColliderBundle {
shape: shape.into(),
mass_properties: ColliderMassProps::Density(0.2).into(),
flags: ColliderFlags {
collision_groups: BIKE_BODY_GROUP,
..Default::default()
}
.into(),
material: ColliderMaterial {
friction: 0.0,
restitution: 0.0,
..Default::default()
}
.into(),
..Default::default() ..Default::default()
}; };
let restitution = Restitution {
coefficient: 0.0,
..Default::default()
};
let mass_properties = ColliderMassProperties::Density(0.2);
let (membership, filter) = BIKE_BODY_COLLISION_GROUP;
let bike_collision_group = CollisionGroups::new(membership, filter);
let bike = commands let bike = commands
.spawn_bundle(bbody) .spawn()
.insert(RigidBody::Dynamic)
.insert_bundle((xform, GlobalTransform::default())) .insert_bundle((xform, GlobalTransform::default()))
.insert(RigidBodyPositionSync::Interpolated { prev_pos: None }) .insert_bundle((
.with_children(|child_builder| { bcollider_shape,
child_builder bike_collision_group,
.spawn_bundle(bcollide) mass_properties,
.insert(ColliderDebugRender { damping,
color: Color::GREEN, restitution,
}) friction,
.insert(CyberBikeCollider) not_sleeping,
.insert(ColliderPositionSync::Discrete); ccd,
))
.insert(TransformInterpolation {
start: None,
end: None,
}) })
.insert(Velocity::zero())
.insert(ExternalForce::default())
.insert(CyberBikeCollider)
.with_children(|rider| { .with_children(|rider| {
rider.spawn_scene(asset_server.load("cyber-bike_no_y_up.glb#Scene0")); rider.spawn_scene(asset_server.load("cyber-bike_no_y_up.glb#Scene0"));
}) })
@ -93,6 +88,10 @@ fn spawn_cyberbike(mut commands: Commands, asset_server: Res<AssetServer>) {
let wheel_positions = vec![-5.1, 4.7, -5.1]; let wheel_positions = vec![-5.1, 4.7, -5.1];
let wheel_y = -1.8f32; let wheel_y = -1.8f32;
// re-set the collision group
let (membership, filter) = BIKE_WHEEL_COLLISION_GROUP;
let wheels_collision_group = CollisionGroups::new(membership, filter);
for (i, &wheel_z) in wheel_positions.iter().enumerate() { for (i, &wheel_z) in wheel_positions.iter().enumerate() {
let (wheel_x, wheel_rad, stiffness) = match i { let (wheel_x, wheel_rad, stiffness) = match i {
0 => (-2.6, 1.0, 0.016), 0 => (-2.6, 1.0, 0.016),
@ -102,47 +101,34 @@ fn spawn_cyberbike(mut commands: Commands, asset_server: Res<AssetServer>) {
}; };
let offset = Vec3::new(wheel_x, wheel_y, wheel_z); let offset = Vec3::new(wheel_x, wheel_y, wheel_z);
let trans = xform.translation + offset; let trans = xform.translation + offset;
let wheel_pos_in_world = Isometry::from_parts(trans.into(), xform.rotation.into()); let wheel_pos_in_world = Transform::from_rotation(xform.rotation).with_translation(trans);
let _wheel_rb = commands let wheel_damping = Damping {
.spawn_bundle(RigidBodyBundle { angular_damping: 0.8,
position: wheel_pos_in_world.into(), ..Default::default()
activation: RigidBodyActivation::cannot_sleep().into(), };
damping: RigidBodyDamping { let wheel_collider = Collider::ball(wheel_rad);
angular_damping: 0.8, let mass_props = ColliderMassProperties::Density(0.001);
..Default::default()
}
.into(),
ccd: RigidBodyCcd {
ccd_enabled: true,
ccd_max_dist: wheel_rad,
ccd_thickness: 0.01,
..Default::default()
}
.into(),
..Default::default()
})
.insert_bundle(ColliderBundle {
material: ColliderMaterial::new(0.0, 0.0).into(),
shape: ColliderShape::ball(wheel_rad).into(),
mass_properties: ColliderMassProps::Density(0.001).into(),
flags: ColliderFlags {
collision_groups: BIKE_WHEEL_GROUP,
..Default::default()
}
.into(),
..Default::default()
})
.insert(ColliderPositionSync::Discrete)
.insert(ColliderDebugRender::from(Color::YELLOW))
.id();
let damping = 0.3; let damping = 0.3;
let prismatic = PrismaticJointBuilder::new(Vec3::Y)
let prismatic = PrismaticJoint::new(Vector::y_axis()) .local_anchor1(offset)
.local_anchor1(offset.into())
.motor_position(-0.4, stiffness, damping); .motor_position(-0.4, stiffness, damping);
let joint = ImpulseJoint::new(bike, prismatic);
commands.spawn_bundle(((JointBuilderComponent::new(prismatic, bike, _wheel_rb)),)); let _wheel_rb = commands
.spawn()
.insert(RigidBody::Dynamic)
.insert_bundle((wheel_pos_in_world, GlobalTransform::default()))
.insert_bundle((
wheel_collider,
mass_props,
wheel_damping,
ccd,
not_sleeping,
joint,
wheels_collision_group,
))
.id();
} }
} }
@ -150,7 +136,7 @@ pub struct CyberBikePlugin;
impl Plugin for CyberBikePlugin { impl Plugin for CyberBikePlugin {
#[cfg(feature = "debug_render")] #[cfg(feature = "debug_render")]
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_plugin(RapierRenderPlugin) app.add_plugin(RapierDebugRenderPlugin::default())
.add_startup_system_to_stage(StartupStage::PostStartup, spawn_cyberbike); .add_startup_system_to_stage(StartupStage::PostStartup, spawn_cyberbike);
} }

View File

@ -1,6 +1,9 @@
use bevy::{ use bevy::{
prelude::*, prelude::{
render::camera::{ActiveCameras, Camera, CameraPlugin}, info, Commands, Component, Entity, Input, KeyCode, ParamSet, PerspectiveCameraBundle,
PerspectiveProjection, Plugin, Quat, Query, Res, ResMut, State, Transform, With,
},
render::camera::{ActiveCamera, Camera3d},
}; };
use crate::{bike::CyberBikeModel, input::InputState}; use crate::{bike::CyberBikeModel, input::InputState};
@ -36,23 +39,23 @@ fn setup_cybercams(mut commands: Commands) {
.insert(CyberCameras::Hero); .insert(CyberCameras::Hero);
commands commands
.spawn_bundle(PerspectiveCameraBundle::with_name("Inactive")) .spawn_bundle(PerspectiveCameraBundle::default())
.insert(CyberCameras::Debug); .insert(CyberCameras::Debug);
} }
fn follow_cyberbike( fn follow_cyberbike(
mut query: QuerySet<( mut query: ParamSet<(
// 0: the bike // 0: the bike
QueryState<&Transform, With<CyberBikeModel>>, Query<&Transform, With<CyberBikeModel>>,
// 1: the cameras // 1: the cameras
QueryState<(&mut Transform, &CyberCameras)>, Query<(&mut Transform, &CyberCameras)>,
)>, )>,
input: Res<InputState>, input: Res<InputState>,
) { ) {
let bike_xform = *query.q0().single(); let bike_xform = *query.p0().single();
let up = bike_xform.translation.normalize(); let up = bike_xform.translation.normalize();
for (mut cam_xform, cam_type) in query.q1().iter_mut() { for (mut cam_xform, cam_type) in query.p1().iter_mut() {
match *cam_type { match *cam_type {
CyberCameras::Hero => { CyberCameras::Hero => {
let look_at = bike_xform.translation + (bike_xform.forward() * 200.0); let look_at = bike_xform.translation + (bike_xform.forward() * 200.0);
@ -79,26 +82,17 @@ fn follow_cyberbike(
} }
fn update_active_camera( fn update_active_camera(
mut active_cams: ResMut<ActiveCameras>, mut active_cams: ResMut<ActiveCamera<Camera3d>>,
state: Res<State<CyberCameras>>, state: Res<State<CyberCameras>>,
mut query: Query<(&mut Camera, &CyberCameras)>, mut query: Query<(&CyberCameras, Entity)>,
) { ) {
active_cams.remove(CameraPlugin::CAMERA_3D); // find the camera with the current state, set it as the ActiveCamera
query
// set all cameras to inactive
for (mut cam, _) in query.iter_mut() {
cam.name = Some("Inactive".to_string());
}
// find the camera with the current state, set its name to be active
for (mut cam, _) in query
.iter_mut() .iter_mut()
.filter(|(_, cybercam)| state.current().eq(cybercam)) .filter(|(cybercam, _)| state.current().eq(cybercam))
{ .for_each(|(_, entity)| {
cam.name = Some(CameraPlugin::CAMERA_3D.to_string()); active_cams.set(entity);
} });
active_cams.add(CameraPlugin::CAMERA_3D);
} }
fn cycle_cam_state(mut state: ResMut<State<CyberCameras>>, mut keys: ResMut<Input<KeyCode>>) { fn cycle_cam_state(mut state: ResMut<State<CyberCameras>>, mut keys: ResMut<Input<KeyCode>>) {

View File

@ -2,7 +2,7 @@ use bevy::{
prelude::*, prelude::*,
render::mesh::{Indices, VertexAttributeValues}, render::mesh::{Indices, VertexAttributeValues},
}; };
use bevy_polyline::{Polyline, PolylineBundle, PolylineMaterial, PolylinePlugin}; use bevy_polyline::prelude::{Polyline, PolylineBundle, PolylineMaterial, PolylinePlugin};
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use crate::{lights::AnimateCyberLightWireframe, planet::CyberPlanet}; use crate::{lights::AnimateCyberLightWireframe, planet::CyberPlanet};

View File

@ -1,5 +1,5 @@
use bevy::{ use bevy::{
app::{Events, ManualEventReader}, ecs::event::{Events, ManualEventReader},
prelude::*, prelude::*,
}; };
@ -13,33 +13,42 @@ pub(crate) struct InputState {
} }
fn update_input(events: Res<Events<GamepadEvent>>, mut istate: ResMut<InputState>) { fn update_input(events: Res<Events<GamepadEvent>>, mut istate: ResMut<InputState>) {
let mut throttle = 0.0;
let mut brake = false;
let mut pitch = 0.0;
let mut yaw = 0.0;
for GamepadEvent(_, ev) in istate.event_reader.iter(&events) { for GamepadEvent(_, ev) in istate.event_reader.iter(&events) {
match *ev { match *ev {
GamepadEventType::ButtonChanged(GamepadButtonType::RightTrigger2, val) => { GamepadEventType::ButtonChanged(GamepadButtonType::RightTrigger2, val) => {
istate.throttle = val; throttle += val;
} }
GamepadEventType::ButtonChanged(GamepadButtonType::LeftTrigger2, val) => { GamepadEventType::ButtonChanged(GamepadButtonType::LeftTrigger2, val) => {
istate.throttle = -val; throttle -= val;
} }
GamepadEventType::ButtonChanged(GamepadButtonType::East, val) => { GamepadEventType::ButtonChanged(GamepadButtonType::East, val) => {
if val > 0.5 { if val > 0.5 {
istate.brake = true; brake = true;
} else { } else {
istate.brake = false; brake = false;
} }
} }
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickX, val) => { GamepadEventType::AxisChanged(GamepadAxisType::LeftStickX, val) => {
istate.yaw = -val; yaw -= val;
} }
// ignore spurious vertical movement for now // ignore spurious vertical movement for now
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickY, val) => { GamepadEventType::AxisChanged(GamepadAxisType::LeftStickY, val) => {
istate.pitch = val; pitch += val;
} }
_ => { _ => {
info!("unhandled gamepad event: {:?}", ev); info!("unhandled gamepad event: {:?}", ev);
} }
} }
} }
istate.throttle = throttle;
istate.brake = brake;
istate.pitch = pitch;
istate.yaw = yaw;
} }
pub struct CyberInputPlugin; pub struct CyberInputPlugin;

View File

@ -27,28 +27,16 @@ fn spawn_planet(
let (mesh, shape) = gen_planet(isphere); let (mesh, shape) = gen_planet(isphere);
let pbody = RigidBodyBundle { let pbody = (RigidBody::Fixed, Ccd { enabled: true });
body_type: RigidBodyType::Static.into(),
ccd: RigidBodyCcd {
ccd_enabled: true,
ccd_thickness: 0.5,
ccd_max_dist: PLANET_RADIUS * 1.05,
..Default::default()
}
.into(),
..Default::default()
};
let pcollide = ColliderBundle { let pcollide = (
shape: shape.into(), shape,
material: ColliderMaterial { Friction {
friction: 0.05, coefficient: 0.05,
restitution: 0.00,
..Default::default() ..Default::default()
} },
.into(), Restitution::new(0.0),
..Default::default() );
};
commands commands
.spawn_bundle(PbrBundle { .spawn_bundle(PbrBundle {
@ -79,7 +67,7 @@ impl Plugin for CyberPlanetPlugin {
// utils // utils
//--------------------------------------------------------------------- //---------------------------------------------------------------------
fn gen_planet(sphere: Icosphere) -> (Mesh, ColliderShape) { fn gen_planet(sphere: Icosphere) -> (Mesh, Collider) {
// straight-up stolen from Bevy's impl of Mesh from Icosphere, so I can do the // straight-up stolen from Bevy's impl of Mesh from Icosphere, so I can do the
// displacement before normals are calculated. // displacement before normals are calculated.
let generated = IcoSphere::new(sphere.subdivisions, |point| { let generated = IcoSphere::new(sphere.subdivisions, |point| {
@ -122,13 +110,13 @@ fn gen_planet(sphere: Icosphere) -> (Mesh, ColliderShape) {
idxs.push([idx[0], idx[1], idx[2]]); idxs.push([idx[0], idx[1], idx[2]]);
} }
let shape = ColliderShape::trimesh(points.iter().map(|p| Point::from_slice(p)).collect(), idxs); let shape = Collider::trimesh(points.iter().map(|p| Vect::from_slice(p)).collect(), idxs);
let indices = Indices::U32(indices); let indices = Indices::U32(indices);
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList); let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.set_indices(Some(indices)); mesh.set_indices(Some(indices));
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, points); mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, points);
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs); mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
(mesh, shape) (mesh, shape)
} }

View File

@ -34,12 +34,12 @@ fn setup_ui(mut commands: Commands, asset_server: Res<AssetServer>) {
} }
fn update_ui( fn update_ui(
state_query: Query<&RigidBodyVelocityComponent, With<CyberBikeBody>>, state_query: Query<&Velocity, With<CyberBikeBody>>,
mut text_query: Query<&mut Text, With<UpText>>, mut text_query: Query<&mut Text, With<UpText>>,
) { ) {
let mut text = text_query.single_mut(); let mut text = text_query.single_mut();
let state = state_query.single(); let state = state_query.single();
text.sections[0].value = format!("spd: {:.2}", state.linvel.magnitude()); text.sections[0].value = format!("spd: {:.2}", state.linvel.length());
} }
pub struct CyberUIPlugin; pub struct CyberUIPlugin;