Compare commits

..

2 commits

Author SHA1 Message Date
Joe Ardent
3d0d86f24c compiles and runs, but crashes 2024-07-15 17:30:26 -07:00
Joe Ardent
4d94f2bfa4 update deps for switching to Avian3d 2024-07-15 17:30:26 -07:00
11 changed files with 172 additions and 121 deletions

23
Cargo.lock generated
View file

@ -284,9 +284,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "avian3d"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a8da53296a1bc166b84f99aa7c6b9d8c10c71f0c022bc4fc72dd1fc49323b29"
checksum = "54325576b6efa46576db611624db749b553d0c66e439862bdc60c43e01f012f9"
dependencies = [
"avian_derive",
"bevy",
@ -1223,9 +1223,9 @@ dependencies = [
[[package]]
name = "blake3"
version = "1.5.2"
version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d08263faac5cde2a4d52b513dadb80846023aade56fcd8fc99ba73ba8050e92"
checksum = "e9ec96fe9a81b5e365f9db71fe00edc4fe4ca2cc7dcb7861f0603012a7caa210"
dependencies = [
"arrayref",
"arrayvec",
@ -1296,9 +1296,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.6.0"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952"
[[package]]
name = "calloop"
@ -1316,13 +1316,12 @@ dependencies = [
[[package]]
name = "cc"
version = "1.1.2"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47de7e88bbbd467951ae7f5a6f34f70d1b4d9cfce53d5fd70f74ebe118b3db56"
checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052"
dependencies = [
"jobserver",
"libc",
"once_cell",
]
[[package]]
@ -3067,7 +3066,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.5.2",
"redox_syscall 0.5.3",
"smallvec",
"windows-targets 0.52.6",
]
@ -3367,9 +3366,9 @@ dependencies = [
[[package]]
name = "redox_syscall"
version = "0.5.2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
dependencies = [
"bitflags 2.6.0",
]

View file

@ -1,7 +1,7 @@
use std::time::{Duration, Instant};
use bevy::{
prelude::{Component, ReflectResource, Resource, Vec3},
prelude::{Component, ReflectResource, Resource},
reflect::Reflect,
};
@ -26,21 +26,6 @@ impl ActionDebugInstant {
}
}
#[derive(Debug, Component)]
pub(super) struct Tunneling {
pub frames: usize,
pub dir: Vec3,
}
impl Default for Tunneling {
fn default() -> Self {
Tunneling {
frames: 15,
dir: Vec3::ZERO,
}
}
}
#[derive(Debug, Resource, Reflect)]
#[reflect(Resource)]
pub struct MovementSettings {

View file

@ -1,6 +1,6 @@
use avian3d::prelude::*;
use avian3d::prelude::{PhysicsPlugins, SubstepCount};
use bevy::{
app::{Startup, Update},
app::Update,
diagnostic::FrameTimeDiagnosticsPlugin,
ecs::reflect::ReflectResource,
prelude::{App, IntoSystemConfigs, Plugin, Resource},
@ -29,14 +29,14 @@ impl Plugin for CyberActionPlugin {
.init_resource::<CyberLean>()
.register_type::<CyberLean>()
.register_type::<CatControllerSettings>()
.add_plugins((
PhysicsPlugins::default(),
FrameTimeDiagnosticsPlugin::default(),
))
.add_plugins((PhysicsPlugins::default(), FrameTimeDiagnosticsPlugin))
.insert_resource(SubstepCount(12))
.add_systems(
Update,
(gravity, cyber_lean, falling_cat, input_forces).chain(),
(
gravity,
(cyber_lean, suspension, falling_cat, input_forces).after(clear_forces),
),
);
}
}

View file

@ -1,17 +1,17 @@
use std::f32::consts::{FRAC_PI_3, FRAC_PI_4};
use avian3d::{
dynamics::solver::xpbd::AngularConstraint, parry::mass_properties::MassProperties, prelude::*,
};
use bevy::prelude::{
Commands, Entity, Quat, Query, Res, ResMut, Time, Transform, Vec3, With, Without,
dynamics::solver::xpbd::AngularConstraint,
prelude::{
ColliderMassProperties, ExternalForce, ExternalTorque, Gravity, LinearVelocity,
PrismaticJoint, RigidBodyQuery,
},
};
use bevy::prelude::{Quat, Query, Res, ResMut, Time, Transform, Vec3, With, Without};
//#[cfg(feature = "inspector")]
//use super::ActionDebugInstant;
use super::{CatControllerSettings, CatControllerState, CyberLean, MovementSettings, Tunneling};
use super::{CatControllerSettings, CatControllerState, CyberLean, MovementSettings};
use crate::{
bike::{CyberBikeBody, CyberSteering, CyberWheel, WheelConfig, BIKE_WHEEL_COLLISION_GROUP},
bike::{CyberBikeBody, CyberFork, CyberSpring, CyberSteering, CyberWheel, WheelConfig},
input::InputState,
};
@ -37,14 +37,42 @@ fn rotate_point(pt: &Vec3, rot: &Quat) -> Vec3 {
/// The gravity vector points from the cyberbike to the center of the planet.
pub(super) fn gravity(
mut query: Query<(&Transform, &mut ExternalForce), With<CyberBikeBody>>,
xform: Query<&Transform, With<CyberBikeBody>>,
settings: Res<MovementSettings>,
mut gravity: ResMut<Gravity>,
#[cfg(feature = "inspector")] mut debug_instant: ResMut<ActionDebugInstant>,
) {
let (xform, mut forces) = query.single_mut();
let xform = xform.single();
*gravity = Gravity(xform.translation.normalize() * -settings.gravity);
forces.clear();
// clear all external forces
}
pub(super) fn clear_forces(mut forces: Query<(&mut ExternalForce, &mut ExternalTorque)>) {
for (mut force, mut torque) in forces.iter_mut() {
force.clear();
torque.clear();
}
}
pub(super) fn suspension(
movment_settings: Res<MovementSettings>,
wheel_config: Res<WheelConfig>,
mass: Query<&ColliderMassProperties, With<CyberBikeBody>>,
mut axels: Query<(&mut ExternalForce, &CyberSpring, &Transform)>,
) {
let mass = if let Ok(mass) = mass.get_single() {
mass.mass.0
} else {
1.0
};
let gravity = movment_settings.gravity;
let mag = -wheel_config.stiffness * mass * gravity;
for (mut force, spring, xform) in axels.iter_mut() {
let spring = mag * spring.0;
let spring = xform.translation + spring;
let _ = force.apply_force(spring);
}
}
/// The desired lean angle, given steering input and speed.
@ -106,26 +134,30 @@ pub(super) fn input_forces(
settings: Res<MovementSettings>,
input: Res<InputState>,
time: Res<Time>,
axle: Query<Entity, With<CyberSteering>>,
fork: Query<&PrismaticJoint, With<CyberFork>>,
mut axle: Query<(RigidBodyQuery, &Transform), With<CyberSteering>>,
mut braking_query: Query<&mut ExternalTorque, With<CyberWheel>>,
mut body_query: Query<
(
Entity,
RigidBodyQuery,
&Transform,
&ColliderMassProperties,
&mut ExternalForce,
),
With<CyberBikeBody>,
(With<CyberBikeBody>, Without<CyberSteering>),
>,
) {
let (bike, xform, mass, mut forces) = body_query.single_mut();
let Ok((mut bike, xform, mass, mut forces)) = body_query.get_single_mut() else {
bevy::log::warn!("no bike body found");
return;
};
let dt = time.delta_seconds();
// thrust
let thrust = xform.forward() * input.throttle * settings.accel;
let point = xform.translation + *xform.back();
*forces.apply_force_at_point(dt * thrust, point, mass.center_of_mass.0);
let _ = *forces.apply_force_at_point(dt * thrust, point, mass.center_of_mass.0);
// brake + thrust
for mut motor in braking_query.iter_mut() {
@ -142,7 +174,14 @@ pub(super) fn input_forces(
// steering
let _angle = yaw_to_angle(input.yaw);
let _axle = axle.single();
//steering.align_orientation(bike, steering, rotation_difference, lagrange,
// compliance, dt)
let (mut axle, xform) = axle.single_mut();
let cur_rot = xform.rotation;
let fork = fork.single();
let axis = fork.free_axis.normalize();
let new = Quat::from_axis_angle(axis, _angle);
let diff = (new - cur_rot).to_scaled_axis();
let mut compliance = 1.0;
fork.align_orientation(&mut axle, &mut bike, diff, &mut compliance, 1.0, dt);
}

View file

@ -37,24 +37,20 @@ pub(super) fn spawn_cyberbike(
let scene = asset_server.load("cb-no-y_up.glb#Scene0");
let spatialbundle = SpatialBundle {
transform: xform,
..Default::default()
};
let body =
let body_collider =
Collider::capsule_endpoints(0.5, Vec3::new(0.0, 0.0, -0.65), Vec3::new(0.0, 0.0, 0.8));
let mass_props = MassPropertiesBundle::new_computed(&body, 0.6);
let bike = commands
.spawn(RigidBody::Dynamic)
.insert(spatialbundle)
.spawn(SpatialBundle::from_transform(xform))
.insert((
body,
mass_props.clone(),
RigidBody::Dynamic,
body_collider,
bike_collision_group,
restitution,
friction,
SleepingDisabled,
CyberBikeBody,
CatControllerState::default(),
ColliderDensity(0.6),
LinearDamping(0.1),
AngularDamping(2.0),
LinearVelocity::ZERO,
@ -68,8 +64,6 @@ pub(super) fn spawn_cyberbike(
..Default::default()
});
})
.insert(CyberBikeBody)
.insert(CatControllerState::default())
.id();
spawn_wheels(&mut commands, bike, &wheel_conf, &mut meshterials);

View file

@ -1,4 +1,5 @@
use bevy::{
math::Vec3,
prelude::{Component, ReflectResource, Resource},
reflect::Reflect,
};
@ -6,12 +7,18 @@ use bevy::{
#[derive(Component)]
pub struct CyberBikeBody;
#[derive(Clone, Component)]
#[derive(Clone, Copy, Component)]
pub struct CyberSteering;
#[derive(Clone, Debug, Component)]
#[derive(Clone, Copy, Debug, Component)]
pub struct CyberWheel;
#[derive(Clone, Debug, Component)]
pub struct CyberSpring(pub Vec3);
#[derive(Clone, Debug, Component)]
pub struct CyberFork;
#[derive(Resource, Reflect)]
#[reflect(Resource)]
pub struct WheelConfig {
@ -35,7 +42,7 @@ impl Default for WheelConfig {
rear_back: 1.0,
y: -0.1,
limits: [-0.5, 0.1],
stiffness: 190.0,
stiffness: 3.0,
damping: 8.0,
radius: 0.25,
thickness: 0.11,

View file

@ -3,7 +3,7 @@ mod components;
mod wheels;
use bevy::{
app::PostStartup,
app::{PostStartup, Startup},
prelude::{App, Assets, Mesh, Plugin, ResMut, StandardMaterial},
};
@ -23,6 +23,6 @@ impl Plugin for CyberBikePlugin {
fn build(&self, app: &mut App) {
app.insert_resource(WheelConfig::default())
.register_type::<WheelConfig>()
.add_systems(PostStartup, spawn_cyberbike);
.add_systems(Startup, spawn_cyberbike);
}
}

View file

@ -1,7 +1,10 @@
use avian3d::prelude::*;
use bevy::prelude::{Torus as Tire, *};
use super::{CyberSteering, CyberWheel, Meshterial, WheelConfig, BIKE_WHEEL_COLLISION_GROUP};
use super::{
CyberFork, CyberSpring, CyberSteering, CyberWheel, Meshterial, WheelConfig,
BIKE_WHEEL_COLLISION_GROUP,
};
pub fn spawn_wheels(
commands: &mut Commands,
@ -12,7 +15,6 @@ pub fn spawn_wheels(
let (membership, filter) = BIKE_WHEEL_COLLISION_GROUP;
let wheels_collision_group = CollisionLayers::new(membership, filter);
let wheel_y = conf.y;
let stiffness = conf.stiffness;
let not_sleeping = SleepingDisabled;
let ccd = SweptCcd::NON_LINEAR.include_dynamic(false);
let limits = conf.limits;
@ -84,11 +86,26 @@ pub fn spawn_wheels(
))
.id();
let axel = if let Some(ref steering) = steering {
commands.spawn((RigidBody::Dynamic, ExternalForce::ZERO, steering.clone()))
let spring = CyberSpring(suspension_axis);
let axel = if let Some(steering) = steering {
commands.spawn((
RigidBody::Dynamic,
ExternalForce::ZERO,
steering,
spring,
Collider::sphere(0.1),
ColliderDensity(0.1),
))
} else {
commands.spawn((RigidBody::Dynamic, ExternalForce::ZERO))
commands.spawn((
RigidBody::Dynamic,
ExternalForce::ZERO,
spring,
Collider::sphere(0.1),
ColliderDensity(0.1),
))
}
.insert(SpatialBundle::default())
.id();
let axel_joint = RevoluteJoint::new(axel, wheel).with_aligned_axis(Vec3::NEG_X);
commands.spawn(axel_joint);
@ -100,7 +117,7 @@ pub fn spawn_wheels(
.with_local_anchor_1(Vec3::new(0.0, 0.0, 0.1))
.with_local_anchor_2(offset)
.with_limits(limits[0], limits[1]);
commands.spawn(joint);
commands.spawn((joint, CyberFork));
} else {
let joint = PrismaticJoint::new(axel, bike)
.with_free_axis(suspension_axis)

View file

@ -81,7 +81,7 @@ fn follow_cyberbike(
// handle input pitch
let angle = input.pitch.powi(3) * MAX_PITCH;
let axis = cam_xform.right();
cam_xform.rotate(Quat::from_axis_angle(axis, angle));
cam_xform.rotate(Quat::from_axis_angle(*axis, angle));
}
CyberCameras::Debug => {
let mut ncx = bike_xform.to_owned();
@ -101,7 +101,7 @@ fn update_active_camera(
) {
// find the camera with the current state, set it as the ActiveCamera
query.iter_mut().for_each(|(mut cam, cyber)| {
if cyber.eq(&state.0) {
if cyber.eq(&state.get()) {
cam.is_active = true;
} else {
cam.is_active = false;
@ -112,13 +112,13 @@ fn update_active_camera(
fn cycle_cam_state(
state: Res<State<CyberCameras>>,
mut next: ResMut<NextState<CyberCameras>>,
mut keys: ResMut<Input<KeyCode>>,
mut keys: ResMut<ButtonInput<KeyCode>>,
) {
if keys.just_pressed(KeyCode::D) {
let new_state = state.0.next();
if keys.just_pressed(KeyCode::KeyD) {
let new_state = state.get().next();
info!("{:?}", new_state);
next.set(new_state);
keys.reset(KeyCode::D);
keys.reset(KeyCode::KeyD);
}
}
@ -132,9 +132,10 @@ impl Plugin for CyberCamPlugin {
fn common(app: &mut bevy::prelude::App) {
app.insert_resource(DebugCamOffset::default())
.add_startup_system(setup_cybercams)
.add_state::<CyberCameras>()
.add_system(cycle_cam_state)
.add_system(update_active_camera)
.add_system(follow_cyberbike);
.add_systems(Startup, setup_cybercams)
.init_state::<CyberCameras>()
.add_systems(
Update,
(cycle_cam_state, update_active_camera, follow_cyberbike),
);
}

View file

@ -4,6 +4,9 @@ use crate::planet::PLANET_RADIUS;
pub const LIGHT_RANGE: f32 = 90.0;
static BLUE: Color = Color::linear_rgb(0.0, 0.0, 1.0);
static PINK: Color = Color::linear_rgb(199.0 / 255.0, 21.0 / 255.0, 113.0 / 255.0);
fn spawn_static_lights(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
@ -12,7 +15,7 @@ fn spawn_static_lights(
let pink_light = PointLight {
intensity: 1_00.0,
range: LIGHT_RANGE,
color: Color::PINK,
color: PINK,
radius: 1.0,
shadows_enabled: true,
..Default::default()
@ -21,7 +24,7 @@ fn spawn_static_lights(
let blue_light = PointLight {
intensity: 1_000.0,
range: LIGHT_RANGE,
color: Color::BLUE,
color: BLUE,
radius: 1.0,
shadows_enabled: true,
..Default::default()
@ -48,16 +51,10 @@ fn spawn_static_lights(
})
.with_children(|builder| {
builder.spawn(PbrBundle {
mesh: meshes.add(
Mesh::try_from(shape::Icosphere {
radius: 10.0,
subdivisions: 2,
})
.unwrap(),
),
mesh: meshes.add(Mesh::from(Sphere::new(10.0))),
material: materials.add(StandardMaterial {
base_color: Color::BLUE,
emissive: Color::PINK,
base_color: BLUE,
emissive: PINK.into(),
..Default::default()
}),
..Default::default()
@ -72,16 +69,10 @@ fn spawn_static_lights(
})
.with_children(|builder| {
builder.spawn(PbrBundle {
mesh: meshes.add(
Mesh::try_from(shape::Icosphere {
radius: 10.0,
subdivisions: 2,
})
.unwrap(),
),
mesh: meshes.add(Mesh::from(Sphere::new(10.0))),
material: materials.add(StandardMaterial {
base_color: Color::PINK,
emissive: Color::BLUE,
base_color: PINK,
emissive: BLUE.into(),
..Default::default()
}),
..Default::default()
@ -92,6 +83,6 @@ fn spawn_static_lights(
pub struct CyberSpaceLightsPlugin;
impl Plugin for CyberSpaceLightsPlugin {
fn build(&self, app: &mut App) {
app.add_startup_system(spawn_static_lights);
app.add_systems(Startup, spawn_static_lights);
}
}

View file

@ -8,7 +8,7 @@ use cyber_rider::{
};
//const CYBER_SKY: Color = Color::rgb(0.07, 0.001, 0.02);
const CYBER_SKY: Color = Color::rgb(0.64, 0.745, 0.937); // a light blue sky
const CYBER_SKY: Color = Color::srgb(0.64, 0.745, 0.937); // a light blue sky
fn main() {
let mut app = App::new();
@ -21,18 +21,36 @@ fn main() {
}),
..Default::default()
}))
.add_plugin(CyberPlanetPlugin)
.add_plugin(CyberInputPlugin)
.add_plugin(CyberActionPlugin)
.add_plugin(CyberCamPlugin)
.add_plugin(CyberSpaceLightsPlugin)
.add_plugin(CyberUIPlugin)
.add_plugin(CyberBikePlugin)
.add_startup_system(disable_mouse_trap)
.add_system(bevy::window::close_on_esc);
.add_plugins((
CyberPlanetPlugin,
CyberInputPlugin,
CyberActionPlugin,
CyberCamPlugin,
CyberSpaceLightsPlugin,
CyberUIPlugin,
CyberBikePlugin,
))
.add_systems(Startup, disable_mouse_trap)
.add_systems(Update, close_on_esc);
#[cfg(feature = "inspector")]
app.add_plugin(CyberGlamorPlugin);
app.run();
}
fn close_on_esc(
mut commands: Commands,
focused_windows: Query<(Entity, &Window)>,
input: Res<ButtonInput<KeyCode>>,
) {
for (window, focus) in focused_windows.iter() {
if !focus.focused {
continue;
}
if input.just_pressed(KeyCode::Escape) {
commands.entity(window).despawn();
}
}
}