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

View file

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

View file

@ -22,65 +22,60 @@ pub struct CyberBikeControl {
pub prev_pitch_error: f32,
}
const BIKE_BODY_GROUP: InteractionGroups = InteractionGroups::new(0b01, 0b01);
const BIKE_WHEEL_GROUP: InteractionGroups = InteractionGroups::new(0b10, 0b10);
const BIKE_BODY_COLLISION_GROUP: (u32, u32) = (0b01, 0b01);
const BIKE_WHEEL_COLLISION_GROUP: (u32, u32) = (0b10, 0b10);
fn spawn_cyberbike(mut commands: Commands, asset_server: Res<AssetServer>) {
let xform = Transform::from_translation(Vec3::X * SPAWN_ALTITUDE)
.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;
bbody.damping.linear_damping = 0.1;
bbody.activation = RigidBodyActivation::cannot_sleep().into();
let ccd = Ccd { enabled: true };
bbody.ccd = RigidBodyCcd {
ccd_enabled: true,
ccd_thickness: 0.2,
ccd_max_dist: 2.7,
..Default::default()
}
.into();
let bcollider_shape =
Collider::capsule(Vec3::new(0.0, 0.0, -2.7), Vec3::new(0.0, 0.0, 2.5), 1.0);
let isometry = Isometry::from_parts(xform.translation.into(), xform.rotation.into());
bbody.position = isometry.into();
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(),
let friction = Friction {
coefficient: 0.0,
..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
.spawn_bundle(bbody)
.spawn()
.insert(RigidBody::Dynamic)
.insert_bundle((xform, GlobalTransform::default()))
.insert(RigidBodyPositionSync::Interpolated { prev_pos: None })
.with_children(|child_builder| {
child_builder
.spawn_bundle(bcollide)
.insert(ColliderDebugRender {
color: Color::GREEN,
.insert_bundle((
bcollider_shape,
bike_collision_group,
mass_properties,
damping,
restitution,
friction,
not_sleeping,
ccd,
))
.insert(TransformInterpolation {
start: None,
end: None,
})
.insert(Velocity::zero())
.insert(ExternalForce::default())
.insert(CyberBikeCollider)
.insert(ColliderPositionSync::Discrete);
})
.with_children(|rider| {
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_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() {
let (wheel_x, wheel_rad, stiffness) = match i {
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 trans = xform.translation + offset;
let wheel_pos_in_world = Isometry::from_parts(trans.into(), xform.rotation.into());
let _wheel_rb = commands
.spawn_bundle(RigidBodyBundle {
position: wheel_pos_in_world.into(),
activation: RigidBodyActivation::cannot_sleep().into(),
damping: RigidBodyDamping {
let wheel_pos_in_world = Transform::from_rotation(xform.rotation).with_translation(trans);
let wheel_damping = Damping {
angular_damping: 0.8,
..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 wheel_collider = Collider::ball(wheel_rad);
let mass_props = ColliderMassProperties::Density(0.001);
let damping = 0.3;
let prismatic = PrismaticJoint::new(Vector::y_axis())
.local_anchor1(offset.into())
let prismatic = PrismaticJointBuilder::new(Vec3::Y)
.local_anchor1(offset)
.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 {
#[cfg(feature = "debug_render")]
fn build(&self, app: &mut App) {
app.add_plugin(RapierRenderPlugin)
app.add_plugin(RapierDebugRenderPlugin::default())
.add_startup_system_to_stage(StartupStage::PostStartup, spawn_cyberbike);
}

View file

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

View file

@ -2,7 +2,7 @@ use bevy::{
prelude::*,
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 crate::{lights::AnimateCyberLightWireframe, planet::CyberPlanet};

View file

@ -1,5 +1,5 @@
use bevy::{
app::{Events, ManualEventReader},
ecs::event::{Events, ManualEventReader},
prelude::*,
};
@ -13,33 +13,42 @@ pub(crate) struct 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) {
match *ev {
GamepadEventType::ButtonChanged(GamepadButtonType::RightTrigger2, val) => {
istate.throttle = val;
throttle += val;
}
GamepadEventType::ButtonChanged(GamepadButtonType::LeftTrigger2, val) => {
istate.throttle = -val;
throttle -= val;
}
GamepadEventType::ButtonChanged(GamepadButtonType::East, val) => {
if val > 0.5 {
istate.brake = true;
brake = true;
} else {
istate.brake = false;
brake = false;
}
}
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickX, val) => {
istate.yaw = -val;
yaw -= val;
}
// ignore spurious vertical movement for now
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickY, val) => {
istate.pitch = val;
pitch += val;
}
_ => {
info!("unhandled gamepad event: {:?}", ev);
}
}
}
istate.throttle = throttle;
istate.brake = brake;
istate.pitch = pitch;
istate.yaw = yaw;
}
pub struct CyberInputPlugin;

View file

@ -27,28 +27,16 @@ fn spawn_planet(
let (mesh, shape) = gen_planet(isphere);
let pbody = RigidBodyBundle {
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 pbody = (RigidBody::Fixed, Ccd { enabled: true });
let pcollide = ColliderBundle {
shape: shape.into(),
material: ColliderMaterial {
friction: 0.05,
restitution: 0.00,
let pcollide = (
shape,
Friction {
coefficient: 0.05,
..Default::default()
}
.into(),
..Default::default()
};
},
Restitution::new(0.0),
);
commands
.spawn_bundle(PbrBundle {
@ -79,7 +67,7 @@ impl Plugin for CyberPlanetPlugin {
// 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
// displacement before normals are calculated.
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]]);
}
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 mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.set_indices(Some(indices));
mesh.set_attribute(Mesh::ATTRIBUTE_POSITION, points);
mesh.set_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, points);
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs);
(mesh, shape)
}

View file

@ -34,12 +34,12 @@ fn setup_ui(mut commands: Commands, asset_server: Res<AssetServer>) {
}
fn update_ui(
state_query: Query<&RigidBodyVelocityComponent, With<CyberBikeBody>>,
state_query: Query<&Velocity, With<CyberBikeBody>>,
mut text_query: Query<&mut Text, With<UpText>>,
) {
let mut text = text_query.single_mut();
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;