Merge branch 'desert-planet'

This commit is contained in:
Joe Ardent 2023-03-21 18:04:35 -07:00
commit 27ba017609
16 changed files with 799 additions and 785 deletions

1055
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -5,31 +5,33 @@ edition = "2021"
[dependencies] [dependencies]
rand = "0.8" rand = "0.8"
bevy_polyline = "0.4" # bevy_polyline = "0.4"
noise = { git = "https://github.com/Razaekel/noise-rs" } noise = { git = "https://github.com/Razaekel/noise-rs" }
hexasphere = "7" hexasphere = "7"
wgpu = "0.14" wgpu = "0.15"
bevy-inspector-egui = "0.17.0" bevy-inspector-egui = "0.18"
# wgpu = "0.12"
[features] [features]
inspector = [] inspector = []
[dependencies.bevy] [dependencies.bevy]
version = "0.9" version = "0.10"
default-features = false default-features = false
features = [ features = [
"bevy_gilrs", "bevy_gilrs",
"bevy_winit", "bevy_winit",
"render",
"png", "png",
"hdr", "hdr",
"x11", "x11",
"bevy_ui",
"bevy_text",
"bevy_gltf",
"bevy_sprite",
] ]
[dependencies.bevy_rapier3d] [dependencies.bevy_rapier3d]
features = ["debug-render-3d"] features = ["debug-render-3d"]
version = "0.20" version = "0.21"
# 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

@ -46,14 +46,12 @@ impl Default for Tunneling {
pub struct MovementSettings { pub struct MovementSettings {
pub accel: f32, pub accel: f32,
pub gravity: f32, pub gravity: f32,
pub sensitivity: f32,
} }
impl Default for MovementSettings { impl Default for MovementSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
sensitivity: 6.0, accel: 20.0,
accel: 40.0,
gravity: 9.8, gravity: 9.8,
} }
} }

View File

@ -1,6 +1,7 @@
use bevy::{ use bevy::{
diagnostic::FrameTimeDiagnosticsPlugin, diagnostic::FrameTimeDiagnosticsPlugin,
prelude::{App, IntoSystemDescriptor, Plugin, ReflectResource, Resource}, ecs::reflect::ReflectResource,
prelude::{App, IntoSystemConfigs, Plugin, Resource},
reflect::Reflect, reflect::Reflect,
}; };
use bevy_rapier3d::prelude::{NoUserData, RapierPhysicsPlugin}; use bevy_rapier3d::prelude::{NoUserData, RapierPhysicsPlugin};
@ -28,19 +29,19 @@ impl Plugin for CyberActionPlugin {
.register_type::<CyberLean>() .register_type::<CyberLean>()
.register_type::<CatControllerSettings>() .register_type::<CatControllerSettings>()
.add_plugin(RapierPhysicsPlugin::<NoUserData>::default()) .add_plugin(RapierPhysicsPlugin::<NoUserData>::default())
.add_startup_system(timestep_setup)
.add_plugin(FrameTimeDiagnosticsPlugin::default()) .add_plugin(FrameTimeDiagnosticsPlugin::default())
.add_system(surface_fix.label("surface_fix")) .add_systems(
.add_system(gravity.label("gravity").before("cat")) (
.add_system(cyber_lean.before("cat").after("gravity")) gravity,
.add_system(falling_cat.label("cat")) cyber_lean,
.add_system(input_forces.label("iforces").after("cat")) falling_cat,
.add_system( input_forces,
tunnel_out drag,
.label("tunnel") tunnel_out,
.before("surface_fix") surface_fix,
.after("drag"), )
) .chain(),
.add_system(surface_fix.label("surface_fix").after("cat")) );
.add_system(drag.label("drag").after("iforces"));
} }
} }

View File

@ -5,14 +5,14 @@ use bevy::prelude::{
}; };
use bevy_rapier3d::prelude::{ use bevy_rapier3d::prelude::{
CollisionGroups, ExternalForce, Group, MultibodyJoint, QueryFilter, RapierConfiguration, CollisionGroups, ExternalForce, Group, MultibodyJoint, QueryFilter, RapierConfiguration,
RapierContext, ReadMassProperties, Velocity, RapierContext, ReadMassProperties, TimestepMode, Velocity,
}; };
#[cfg(feature = "inspector")] #[cfg(feature = "inspector")]
use super::ActionDebugInstant; use super::ActionDebugInstant;
use super::{CatControllerSettings, CatControllerState, CyberLean, MovementSettings, Tunneling}; use super::{CatControllerSettings, CatControllerState, CyberLean, MovementSettings, Tunneling};
use crate::{ use crate::{
bike::{CyberBikeBody, CyberSteering, CyberWheel, BIKE_WHEEL_COLLISION_GROUP}, bike::{CyberBikeBody, CyberSteering, CyberWheel, WheelConfig, BIKE_WHEEL_COLLISION_GROUP},
input::InputState, input::InputState,
}; };
@ -27,7 +27,7 @@ fn yaw_to_angle(yaw: f32) -> f32 {
fn rotate_point(pt: &Vec3, rot: &Quat) -> Vec3 { fn rotate_point(pt: &Vec3, rot: &Quat) -> Vec3 {
// thanks to https://danceswithcode.net/engineeringnotes/quaternions/quaternions.html // thanks to https://danceswithcode.net/engineeringnotes/quaternions/quaternions.html
let [x, y, z] = pt.to_array(); let [x, y, z] = pt.normalize().to_array();
let qpt = Quat::from_xyzw(x, y, z, 0.0); let qpt = Quat::from_xyzw(x, y, z, 0.0);
// p' = rot^-1 * qpt * rot // p' = rot^-1 * qpt * rot
let rot_qpt = rot.inverse() * qpt * *rot; let rot_qpt = rot.inverse() * qpt * *rot;
@ -36,13 +36,31 @@ fn rotate_point(pt: &Vec3, rot: &Quat) -> Vec3 {
-Vec3::from_array([rot_qpt.x, rot_qpt.y, rot_qpt.z]) -Vec3::from_array([rot_qpt.x, rot_qpt.y, rot_qpt.z])
} }
pub(super) fn timestep_setup(mut config: ResMut<RapierConfiguration>) {
let ts = TimestepMode::Fixed {
dt: 1.0 / 60.0,
substeps: 2,
};
config.timestep_mode = ts;
}
/// The gravity vector points from the cyberbike to the center of the planet. /// The gravity vector points from the cyberbike to the center of the planet.
pub(super) fn gravity( pub(super) fn gravity(
mut query: Query<(&Transform, &mut ExternalForce), With<CyberBikeBody>>, mut query: Query<(&Transform, &mut ExternalForce), With<CyberBikeBody>>,
settings: Res<MovementSettings>, settings: Res<MovementSettings>,
mut rapier_config: ResMut<RapierConfiguration>, mut rapier_config: ResMut<RapierConfiguration>,
#[cfg(feature = "inspector")] mut debug_instant: ResMut<ActionDebugInstant>,
) { ) {
let (xform, mut forces) = query.single_mut(); let (xform, mut forces) = query.single_mut();
#[cfg(feature = "inspectorb")]
{
if debug_instant.elapsed().as_millis() > 6000 {
dbg!(&forces);
debug_instant.reset();
}
}
rapier_config.gravity = xform.translation.normalize() * -settings.gravity; rapier_config.gravity = xform.translation.normalize() * -settings.gravity;
forces.force = Vec3::ZERO; forces.force = Vec3::ZERO;
forces.torque = Vec3::ZERO; forces.torque = Vec3::ZERO;
@ -80,7 +98,6 @@ pub(super) fn falling_cat(
time: Res<Time>, time: Res<Time>,
settings: Res<CatControllerSettings>, settings: Res<CatControllerSettings>,
lean: Res<CyberLean>, lean: Res<CyberLean>,
#[cfg(feature = "inspector")] mut debug_instant: ResMut<ActionDebugInstant>,
) { ) {
let (xform, mut forces, mut control_vars) = bike_query.single_mut(); let (xform, mut forces, mut control_vars) = bike_query.single_mut();
let world_up = xform.translation.normalize(); let world_up = xform.translation.normalize();
@ -100,13 +117,6 @@ pub(super) fn falling_cat(
if mag.is_finite() { if mag.is_finite() {
forces.torque += xform.back() * mag; forces.torque += xform.back() * mag;
} }
#[cfg(feature = "inspector")]
{
if debug_instant.elapsed().as_millis() > 1000 {
dbg!(&control_vars, mag, &target_up);
debug_instant.reset();
}
}
} }
} }
@ -129,15 +139,20 @@ pub(super) fn input_forces(
let force = ExternalForce::at_point(thrust, point, xform.translation); let force = ExternalForce::at_point(thrust, point, xform.translation);
*forces += force; *forces += force;
// brake // brake + thrust
for mut motor in braking_query.iter_mut() { for mut motor in braking_query.iter_mut() {
let factor = if input.brake { 500.00 } else { 0.0 }; let factor = if input.brake {
500.00
} else {
input.throttle * settings.accel
};
let speed = if input.brake { 0.0 } else { -70.0 };
motor.data = (*motor motor.data = (*motor
.data .data
.as_revolute_mut() .as_revolute_mut()
.unwrap() .unwrap()
.set_motor_max_force(factor) .set_motor_max_force(factor)
.set_motor_velocity(0.0, factor)) .set_motor_velocity(speed, factor))
.into(); .into();
} }
@ -159,23 +174,31 @@ pub(super) fn surface_fix(
(Entity, &Transform, &mut CollisionGroups), (Entity, &Transform, &mut CollisionGroups),
(With<CyberWheel>, Without<Tunneling>), (With<CyberWheel>, Without<Tunneling>),
>, >,
span_query: Query<&Transform, With<CyberWheel>>,
config: Res<WheelConfig>,
context: Res<RapierContext>, context: Res<RapierContext>,
) { ) {
// assume the body is not below the planet surface let mut wheels = Vec::new();
for xform in span_query.iter() {
wheels.push(xform);
}
let span = (wheels[1].translation - wheels[0].translation).normalize();
for (entity, xform, mut cgroups) in wheel_query.iter_mut() { for (entity, xform, mut cgroups) in wheel_query.iter_mut() {
let ray_dir = xform.translation.normalize(); //let ray_dir = xform.translation.normalize();
let ray_dir = xform.right().cross(span).normalize();
if let Some(hit) = context.cast_ray_and_get_normal( if let Some(hit) = context.cast_ray_and_get_normal(
xform.translation, xform.translation,
ray_dir, ray_dir,
10.0, config.radius * 1.1,
false, false,
QueryFilter::only_fixed(), QueryFilter::only_fixed(),
) { ) {
cgroups.memberships = Group::NONE; cgroups.memberships = Group::NONE;
cgroups.filters = Group::NONE; cgroups.filters = Group::NONE;
commands.entity(entity).insert(Tunneling { commands.entity(entity).insert(Tunneling {
frames: 10, frames: 3,
dir: -hit.1.normal, dir: hit.1.normal,
}); });
} }
} }

View File

@ -16,7 +16,7 @@ pub(super) fn spawn_cyberbike(
wheel_conf: Res<WheelConfig>, wheel_conf: Res<WheelConfig>,
mut meshterials: Meshterial, mut meshterials: Meshterial,
) { ) {
let altitude = PLANET_RADIUS - 180.0; let altitude = PLANET_RADIUS - 10.0;
let mut xform = Transform::from_translation(Vec3::X * altitude) let mut xform = Transform::from_translation(Vec3::X * 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()));
@ -55,7 +55,7 @@ pub(super) fn spawn_cyberbike(
.spawn(RigidBody::Dynamic) .spawn(RigidBody::Dynamic)
.insert(spatialbundle) .insert(spatialbundle)
.insert(( .insert((
Collider::capsule(Vec3::new(0.0, 0.0, -0.65), Vec3::new(0.0, 0.0, 0.8), 0.50), Collider::capsule(Vec3::new(0.0, 0.0, -0.65), Vec3::new(0.0, 0.0, 0.8), 0.5),
bike_collision_group, bike_collision_group,
mass_properties, mass_properties,
damping, damping,

View File

@ -22,6 +22,7 @@ pub struct WheelConfig {
pub stiffness: f32, pub stiffness: f32,
pub damping: f32, pub damping: f32,
pub radius: f32, pub radius: f32,
pub thickness: f32,
pub friction: f32, pub friction: f32,
pub restitution: f32, pub restitution: f32,
pub density: f32, pub density: f32,
@ -36,10 +37,11 @@ impl Default for WheelConfig {
limits: [-0.5, 0.1], limits: [-0.5, 0.1],
stiffness: 50.0, stiffness: 50.0,
damping: 8.0, damping: 8.0,
radius: 0.3, radius: 0.38,
thickness: 0.2,
friction: 1.2, friction: 1.2,
restitution: 0.8, restitution: 0.95,
density: 0.6, density: 0.9,
} }
} }
} }

View File

@ -2,7 +2,9 @@ mod body;
mod components; mod components;
mod wheels; mod wheels;
use bevy::prelude::{App, Assets, Mesh, Plugin, ResMut, StandardMaterial, StartupStage}; use bevy::prelude::{
App, Assets, IntoSystemConfig, Mesh, Plugin, ResMut, StandardMaterial, StartupSet,
};
use bevy_rapier3d::prelude::Group; use bevy_rapier3d::prelude::Group;
pub(crate) use self::components::*; pub(crate) use self::components::*;
@ -21,6 +23,6 @@ impl Plugin for CyberBikePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.insert_resource(WheelConfig::default()) app.insert_resource(WheelConfig::default())
.register_type::<WheelConfig>() .register_type::<WheelConfig>()
.add_startup_system_to_stage(StartupStage::PostStartup, spawn_cyberbike); .add_startup_system(spawn_cyberbike.in_base_set(StartupSet::PostStartup));
} }
} }

View File

@ -17,6 +17,7 @@ pub fn spawn_tires(
let wheels_collision_group = CollisionGroups::new(membership, filter); let wheels_collision_group = CollisionGroups::new(membership, filter);
let wheel_y = conf.y; let wheel_y = conf.y;
let wheel_rad = conf.radius; let wheel_rad = conf.radius;
let _tire_thickness = conf.thickness;
let stiffness = conf.stiffness; let stiffness = conf.stiffness;
let not_sleeping = Sleeping::disabled(); let not_sleeping = Sleeping::disabled();
let ccd = Ccd { enabled: true }; let ccd = Ccd { enabled: true };
@ -28,6 +29,7 @@ pub fn spawn_tires(
radius: wheel_rad, radius: wheel_rad,
..Default::default() ..Default::default()
}; };
let material = StandardMaterial { let material = StandardMaterial {
base_color: Color::Rgba { base_color: Color::Rgba {
red: 0.01, red: 0.01,
@ -74,6 +76,7 @@ pub fn spawn_tires(
linear_damping: 0.8, linear_damping: 0.8,
..Default::default() ..Default::default()
}; };
let wheel_collider = Collider::ball(wheel_rad); let wheel_collider = Collider::ball(wheel_rad);
let mass_props = ColliderMassProperties::Density(conf.density); let mass_props = ColliderMassProperties::Density(conf.density);
let damping = conf.damping; let damping = conf.damping;
@ -97,7 +100,7 @@ pub fn spawn_tires(
let axel_parent_entity = if let Some(steering) = steering { let axel_parent_entity = if let Some(steering) = steering {
let neck_builder = let neck_builder =
RevoluteJointBuilder::new(rake_vec).local_anchor1(Vec3::new(0.0, 0.0, 0.1)); // this adds another 0.1m of trail RevoluteJointBuilder::new(rake_vec).local_anchor1(Vec3::new(0.0, -0.08, 0.1)); // this adds another 0.1m of trail
let neck_joint = MultibodyJoint::new(fork_rb_entity, neck_builder); let neck_joint = MultibodyJoint::new(fork_rb_entity, neck_builder);
let neck = commands let neck = commands
.spawn(RigidBody::Dynamic) .spawn(RigidBody::Dynamic)
@ -110,24 +113,29 @@ pub fn spawn_tires(
fork_rb_entity fork_rb_entity
}; };
let revolute_builder = RevoluteJointBuilder::new(Vec3::X); let axel_builder = RevoluteJointBuilder::new(Vec3::X);
let axel_joint = MultibodyJoint::new(axel_parent_entity, revolute_builder); let axel_joint = MultibodyJoint::new(axel_parent_entity, axel_builder);
// re-orient the joint so that the wheel is correctly oriented
//let real_axel = *axel_joint.data.set_local_axis1(Vec3::X);
//axel_joint.data = real_axel;
commands.spawn(pbr_bundle.clone()).insert(( commands
wheel_collider, .spawn(pbr_bundle.clone())
mass_props, .insert((
wheel_damping, wheel_collider,
ccd, mass_props,
not_sleeping, wheel_damping,
axel_joint, ccd,
wheels_collision_group, not_sleeping,
friction, axel_joint,
CyberWheel, wheels_collision_group,
ExternalForce::default(), friction,
Restitution::new(conf.restitution), CyberWheel,
SpatialBundle::default(), ExternalForce::default(),
TransformInterpolation::default(), Restitution::new(conf.restitution),
RigidBody::Dynamic, TransformInterpolation::default(),
)); RigidBody::Dynamic,
))
.insert(SpatialBundle::default());
} }
} }

View File

@ -5,8 +5,9 @@ use crate::{bike::CyberBikeBody, input::InputState};
// 85 degrees in radians // 85 degrees in radians
const MAX_PITCH: f32 = 1.48353; const MAX_PITCH: f32 = 1.48353;
#[derive(Clone, Copy, Eq, PartialEq, Debug, Hash, Component)] #[derive(Clone, Copy, Eq, PartialEq, Debug, Hash, Component, States, Default)]
enum CyberCameras { enum CyberCameras {
#[default]
Hero, Hero,
Debug, Debug,
} }
@ -42,15 +43,32 @@ fn setup_cybercams(mut commands: Commands) {
fov: std::f32::consts::FRAC_PI_3, fov: std::f32::consts::FRAC_PI_3,
..Default::default() ..Default::default()
}; };
let fog_settings = FogSettings {
color: Color::rgba(0.1, 0.2, 0.4, 1.0),
directional_light_color: Color::rgba(1.0, 0.95, 0.75, 0.5),
directional_light_exponent: 30.0,
falloff: FogFalloff::from_visibility_colors(
350.0, /* distance in world units up to which objects retain visibility (>= 5%
* contrast) */
Color::rgb(0.35, 0.5, 0.66), /* atmospheric extinction color (after light is lost
* due to absorption by atmospheric particles) */
Color::rgb(0.8, 0.844, 1.0), /* atmospheric inscattering color (light gained due to
* scattering from the sun) */
),
};
commands commands
.spawn(Camera3dBundle { .spawn(Camera3dBundle {
projection: bevy::render::camera::Projection::Perspective(hero_projection), projection: bevy::render::camera::Projection::Perspective(hero_projection),
..Default::default() ..Default::default()
}) })
.insert(fog_settings.clone())
.insert(CyberCameras::Hero); .insert(CyberCameras::Hero);
commands commands
.spawn(Camera3dBundle::default()) .spawn(Camera3dBundle::default())
.insert(fog_settings)
.insert(CyberCameras::Debug); .insert(CyberCameras::Debug);
} }
@ -99,7 +117,7 @@ fn update_active_camera(
) { ) {
// find the camera with the current state, set it as the ActiveCamera // find the camera with the current state, set it as the ActiveCamera
query.iter_mut().for_each(|(mut cam, cyber)| { query.iter_mut().for_each(|(mut cam, cyber)| {
if cyber.eq(state.current()) { if cyber.eq(&state.0) {
cam.is_active = true; cam.is_active = true;
} else { } else {
cam.is_active = false; cam.is_active = false;
@ -107,11 +125,15 @@ fn update_active_camera(
}); });
} }
fn cycle_cam_state(mut state: ResMut<State<CyberCameras>>, mut keys: ResMut<Input<KeyCode>>) { fn cycle_cam_state(
state: Res<State<CyberCameras>>,
mut next: ResMut<NextState<CyberCameras>>,
mut keys: ResMut<Input<KeyCode>>,
) {
if keys.just_pressed(KeyCode::D) { if keys.just_pressed(KeyCode::D) {
let new_state = state.current().next(); let new_state = state.0.next();
info!("{:?}", new_state); info!("{:?}", new_state);
state.set(new_state).unwrap(); next.set(new_state);
keys.reset(KeyCode::D); keys.reset(KeyCode::D);
} }
} }
@ -127,7 +149,7 @@ impl Plugin for CyberCamPlugin {
fn common(app: &mut bevy::prelude::App) { fn common(app: &mut bevy::prelude::App) {
app.insert_resource(DebugCamOffset::default()) app.insert_resource(DebugCamOffset::default())
.add_startup_system(setup_cybercams) .add_startup_system(setup_cybercams)
.add_state(CyberCameras::Hero) .add_state::<CyberCameras>()
.add_system(cycle_cam_state) .add_system(cycle_cam_state)
.add_system(update_active_camera) .add_system(update_active_camera)
.add_system(follow_cyberbike); .add_system(follow_cyberbike);

View File

@ -1,80 +1,13 @@
use bevy::{ use bevy::prelude::{App, Color, Plugin};
prelude::*,
render::mesh::{Indices, VertexAttributeValues},
};
use bevy_polyline::prelude::{Polyline, PolylineBundle, PolylineMaterial, PolylinePlugin};
use rand::{thread_rng, Rng};
use crate::{lights::AnimateCyberLightWireframe, planet::CyberPlanet}; // use crate::planet::CyberPlanet;
pub const BISEXY_COLOR: Color = Color::hsla(292.0, 0.9, 0.60, 1.1); pub const BISEXY_COLOR: Color = Color::hsla(292.0, 0.9, 0.60, 1.1);
fn wireframe_planet(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut polylines: ResMut<Assets<Polyline>>,
mut polymats: ResMut<Assets<PolylineMaterial>>,
query: Query<&Handle<Mesh>, With<CyberPlanet>>,
) {
let handle = query.single();
let mesh = meshes.get_mut(handle).unwrap();
let vertices = mesh.attribute(Mesh::ATTRIBUTE_POSITION).unwrap();
let mut pts = Vec::with_capacity(vertices.len());
if let VertexAttributeValues::Float32x3(verts) = vertices {
let indices = mesh.indices().unwrap();
if let Indices::U32(indices) = indices {
for i in indices.iter() {
let v = verts[*i as usize];
let v = Vec3::from_slice(&v);
pts.push(v);
}
}
}
let mut verts = Vec::with_capacity((pts.len() as f32 * 1.4) as usize);
for pts in pts.chunks(3) {
if pts.len() > 1 {
verts.extend_from_slice(pts);
verts.push(Vec3::NAN);
}
}
// don't need the indices anymore
mesh.duplicate_vertices();
mesh.compute_flat_normals();
commands.spawn(PolylineBundle {
polyline: polylines.add(Polyline { vertices: verts }),
material: polymats.add(PolylineMaterial {
width: 101.0,
color: BISEXY_COLOR,
perspective: true,
depth_bias: -0.001,
}),
..Default::default()
});
}
fn wireframify_lights(mut lights: Query<&mut AnimateCyberLightWireframe>) {
let chance = 0.005;
let rng = &mut thread_rng();
for mut light in lights.iter_mut() {
if rng.gen::<f32>() < chance {
let new = !light.wired;
light.wired = new;
}
}
}
// public plugin // public plugin
pub struct CyberGlamorPlugin; pub struct CyberGlamorPlugin;
impl Plugin for CyberGlamorPlugin { impl Plugin for CyberGlamorPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
#[cfg(feature = "inspector")]
{ {
use bevy_rapier3d::render::{ use bevy_rapier3d::render::{
DebugRenderMode, DebugRenderStyle, RapierDebugRenderPlugin, DebugRenderMode, DebugRenderStyle, RapierDebugRenderPlugin,
@ -97,9 +30,5 @@ impl Plugin for CyberGlamorPlugin {
app.add_plugin(rplugin); app.add_plugin(rplugin);
} }
app.add_startup_system_to_stage(StartupStage::PostStartup, wireframe_planet)
.add_system(wireframify_lights)
.add_plugin(PolylinePlugin);
} }
} }

View File

@ -1,4 +1,8 @@
use bevy::{prelude::*, utils::HashSet}; use bevy::{
input::gamepad::{GamepadAxisChangedEvent, GamepadButtonChangedEvent, GamepadEvent},
prelude::*,
utils::HashSet,
};
use crate::camera::DebugCamOffset; use crate::camera::DebugCamOffset;
@ -46,39 +50,42 @@ fn update_debug_cam(mut offset: ResMut<DebugCamOffset>, mut keys: ResMut<Input<K
} }
fn update_input(mut events: EventReader<GamepadEvent>, mut istate: ResMut<InputState>) { fn update_input(mut events: EventReader<GamepadEvent>, mut istate: ResMut<InputState>) {
for GamepadEvent { for pad_event in events.iter() {
gamepad: _, match pad_event {
event_type: ev, GamepadEvent::Button(button_event) => {
} in events.iter() let GamepadButtonChangedEvent {
{ button_type, value, ..
match *ev { } = button_event;
GamepadEventType::ButtonChanged(GamepadButtonType::RightTrigger2, val) => { match button_type {
istate.throttle = val; GamepadButtonType::RightTrigger2 => istate.throttle = *value,
} GamepadButtonType::LeftTrigger2 => istate.throttle = -value,
GamepadEventType::ButtonChanged(GamepadButtonType::LeftTrigger2, val) => { GamepadButtonType::East => {
istate.throttle = -val; if value > &0.5 {
} istate.brake = true;
GamepadEventType::ButtonChanged(GamepadButtonType::East, val) => { } else {
if val > 0.5 { istate.brake = false;
istate.brake = true; }
} else { }
istate.brake = false; _ => info!("unhandled button press: {button_event:?}"),
} }
} }
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickX, val) => { GamepadEvent::Axis(axis_event) => {
istate.yaw = val; let GamepadAxisChangedEvent {
} axis_type, value, ..
// ignore spurious vertical movement for now } = axis_event;
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickY, val) => { match axis_type {
istate.pitch = val; GamepadAxisType::LeftStickX => {
} istate.yaw = *value;
_ => { }
info!("unhandled gamepad event: {:?}", ev); GamepadAxisType::RightStickY => {
istate.pitch = *value;
}
_ => info!("unhandled axis event: {axis_event:?}"),
}
} }
GamepadEvent::Connection(_) => {}
} }
} }
//dbg!(&istate);
} }
pub struct CyberInputPlugin; pub struct CyberInputPlugin;

View File

@ -1,6 +1,7 @@
use bevy::{ use bevy::{
ecs::schedule::StageLabel, ecs::schedule::SystemSet,
prelude::{ResMut, SystemLabel, Vec3, Windows}, prelude::{Query, Vec3, Window, With},
window::PrimaryWindow,
}; };
pub mod action; pub mod action;
@ -12,7 +13,7 @@ pub mod lights;
pub mod planet; pub mod planet;
pub mod ui; pub mod ui;
#[derive(Clone, Debug, Hash, PartialEq, Eq, SystemLabel, StageLabel)] #[derive(Clone, Debug, Hash, PartialEq, Eq, SystemSet)]
pub enum Label { pub enum Label {
Geometry, Geometry,
Glamor, Glamor,
@ -20,10 +21,10 @@ pub enum Label {
Action, Action,
} }
pub fn disable_mouse_trap(mut windows: ResMut<Windows>) { pub fn disable_mouse_trap(mut window: Query<&mut Window, With<PrimaryWindow>>) {
let window = windows.get_primary_mut().unwrap(); let mut window = window.get_single_mut().unwrap();
window.set_cursor_grab_mode(bevy::window::CursorGrabMode::None); window.cursor.grab_mode = bevy::window::CursorGrabMode::None;
window.set_cursor_visibility(true); window.cursor.visible = true;
} }
pub fn random_unit_vec(r: &mut impl rand::prelude::Rng) -> Vec3 { pub fn random_unit_vec(r: &mut impl rand::prelude::Rng) -> Vec3 {

View File

@ -1,96 +1,9 @@
use std::f32::consts::TAU; use bevy::{pbr::CascadeShadowConfigBuilder, prelude::*};
use bevy::prelude::*;
use rand::prelude::*;
use crate::planet::PLANET_RADIUS; use crate::planet::PLANET_RADIUS;
pub const LIGHT_RANGE: f32 = 90.0; pub const LIGHT_RANGE: f32 = 90.0;
#[derive(Component)]
struct AnimatedCyberLight {
axis: Vec3,
rate: f32,
}
#[derive(Component, Default)]
pub(crate) struct AnimateCyberLightWireframe {
pub wired: bool,
}
fn spawn_moving_lights(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let rng = &mut thread_rng();
// spawn orbiting bisexual lights
for _ in 0..655 {
// mechanics
let axis = crate::random_unit_vec(rng);
let angle = rng.gen_range(0.0..TAU);
let rate: f32 = rng.gen_range(7.0..10.0);
let rate = rate.to_radians();
let rotation = Quat::from_axis_angle(axis, angle);
let altitude = PLANET_RADIUS + rng.gen_range(8.0..20.0);
let perp = axis.any_orthonormal_vector();
let translation = perp * altitude;
let transform = Transform::from_translation(translation);
// optics
let hue = rng.gen_range(240.0..300.0);
let saturation = rng.gen_range(0.85..0.99);
let lightness = rng.gen_range(0.3..0.7);
let color = Color::hsl(hue, saturation, lightness);
let intensity = rng.gen_range(900.0..1300.0);
let radius = rng.gen::<f32>() * 2.2; // why can't this infer the gen type?
let point_light = PointLight {
intensity,
range: LIGHT_RANGE,
color,
radius: radius - 0.1,
shadows_enabled: true,
..Default::default()
};
let sbundle = SpatialBundle {
transform: Transform::from_rotation(rotation),
..Default::default()
};
commands
// first, spawn an entity with a transform we can rotate
.spawn((AnimatedCyberLight { axis, rate },))
.insert(sbundle)
.with_children(|parent| {
parent
// now spawn a child entity with a pointlight, and a relative transform that's
// just translation from the parent
.spawn(PointLightBundle {
transform,
point_light,
..Default::default()
})
.with_children(|builder| {
builder
// now a simple mesh to show a wireframe.
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere {
radius,
subdivisions: 1,
})),
material: materials.add(StandardMaterial {
base_color: Color::hsla(272.0, 0.7, 0.56, 0.7),
emissive: color,
..Default::default()
}),
..Default::default()
})
.insert(AnimateCyberLightWireframe::default());
}); // mesh child
}); // light child
}
}
fn spawn_static_lights( fn spawn_static_lights(
mut commands: Commands, mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
@ -119,6 +32,13 @@ fn spawn_static_lights(
brightness: 0.2, brightness: 0.2,
}); });
let _cascade_shadow_config = CascadeShadowConfigBuilder {
first_cascade_far_bound: 0.3,
maximum_distance: 3.0,
..default()
}
.build();
// up light // up light
commands commands
.spawn(PointLightBundle { .spawn(PointLightBundle {
@ -128,10 +48,13 @@ fn spawn_static_lights(
}) })
.with_children(|builder| { .with_children(|builder| {
builder.spawn(PbrBundle { builder.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere { mesh: meshes.add(
radius: 10.0, Mesh::try_from(shape::Icosphere {
subdivisions: 2, radius: 10.0,
})), subdivisions: 2,
})
.unwrap(),
),
material: materials.add(StandardMaterial { material: materials.add(StandardMaterial {
base_color: Color::BLUE, base_color: Color::BLUE,
emissive: Color::PINK, emissive: Color::PINK,
@ -149,10 +72,13 @@ fn spawn_static_lights(
}) })
.with_children(|builder| { .with_children(|builder| {
builder.spawn(PbrBundle { builder.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere { mesh: meshes.add(
radius: 10.0, Mesh::try_from(shape::Icosphere {
subdivisions: 2, radius: 10.0,
})), subdivisions: 2,
})
.unwrap(),
),
material: materials.add(StandardMaterial { material: materials.add(StandardMaterial {
base_color: Color::PINK, base_color: Color::PINK,
emissive: Color::BLUE, emissive: Color::BLUE,
@ -163,20 +89,9 @@ fn spawn_static_lights(
}); });
} }
fn orbit_lights(time: Res<Time>, mut query: Query<(&mut Transform, &AnimatedCyberLight)>) {
let dt = time.delta_seconds();
for (mut transform, light) in query.iter_mut() {
let AnimatedCyberLight { axis, rate } = *light;
let theta = rate * dt;
transform.rotation *= Quat::from_axis_angle(axis, theta);
}
}
pub struct CyberSpaceLightsPlugin; pub struct CyberSpaceLightsPlugin;
impl Plugin for CyberSpaceLightsPlugin { impl Plugin for CyberSpaceLightsPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_startup_system(spawn_static_lights) app.add_startup_system(spawn_static_lights);
.add_startup_system(spawn_moving_lights)
.add_system(orbit_lights);
} }
} }

View File

@ -1,27 +1,27 @@
use bevy::prelude::*; use bevy::prelude::*;
#[cfg(feature = "inspector")]
use cyber_rider::glamor::CyberGlamorPlugin;
use cyber_rider::{ use cyber_rider::{
action::CyberActionPlugin, bike::CyberBikePlugin, camera::CyberCamPlugin, disable_mouse_trap, action::CyberActionPlugin, bike::CyberBikePlugin, camera::CyberCamPlugin, disable_mouse_trap,
glamor::CyberGlamorPlugin, input::CyberInputPlugin, lights::CyberSpaceLightsPlugin, input::CyberInputPlugin, lights::CyberSpaceLightsPlugin, planet::CyberPlanetPlugin,
planet::CyberPlanetPlugin, ui::CyberUIPlugin, ui::CyberUIPlugin,
}; };
const CYBER_SKY: Color = Color::rgb(0.07, 0.001, 0.02); //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::rgb(0.64, 0.745, 0.937); // a light blue sky
fn main() { fn main() {
let mut app = App::new(); let mut app = App::new();
app.insert_resource(Msaa { samples: 4 }) app.insert_resource(Msaa::Sample4)
.insert_resource(ClearColor(CYBER_SKY)) .insert_resource(ClearColor(CYBER_SKY))
.add_plugins(DefaultPlugins.set(WindowPlugin { .add_plugins(DefaultPlugins.set(WindowPlugin {
window: WindowDescriptor { primary_window: Some(Window {
width: 2560.0, resolution: (2560.0, 1440.0).into(),
height: 1440.0,
..Default::default() ..Default::default()
}, }),
..Default::default() ..Default::default()
})) }))
.add_plugin(CyberPlanetPlugin) .add_plugin(CyberPlanetPlugin)
.add_plugin(CyberGlamorPlugin)
.add_plugin(CyberInputPlugin) .add_plugin(CyberInputPlugin)
.add_plugin(CyberActionPlugin) .add_plugin(CyberActionPlugin)
.add_plugin(CyberCamPlugin) .add_plugin(CyberCamPlugin)
@ -31,5 +31,8 @@ fn main() {
.add_startup_system(disable_mouse_trap) .add_startup_system(disable_mouse_trap)
.add_system(bevy::window::close_on_esc); .add_system(bevy::window::close_on_esc);
#[cfg(feature = "inspector")]
app.add_plugin(CyberGlamorPlugin);
app.run(); app.run();
} }

View File

@ -9,7 +9,7 @@ use wgpu::PrimitiveTopology;
use crate::Label; use crate::Label;
pub const PLANET_RADIUS: f32 = 6000.0; pub const PLANET_RADIUS: f32 = 3_000.0;
#[derive(Component)] #[derive(Component)]
pub struct CyberPlanet; pub struct CyberPlanet;
@ -19,7 +19,7 @@ fn spawn_planet(
mut meshes: ResMut<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>, mut materials: ResMut<Assets<StandardMaterial>>,
) { ) {
let color = Color::rgb(0.2, 0.1, 0.2); let color = Color::rgb(0.74, 0.5334, 0.176);
let isphere = Icosphere { let isphere = Icosphere {
radius: PLANET_RADIUS, radius: PLANET_RADIUS,
subdivisions: 88, subdivisions: 88,
@ -43,9 +43,9 @@ fn spawn_planet(
mesh: meshes.add(mesh), mesh: meshes.add(mesh),
material: materials.add(StandardMaterial { material: materials.add(StandardMaterial {
base_color: color, base_color: color,
metallic: 0.1, metallic: 0.3,
perceptual_roughness: 0.3, perceptual_roughness: 0.3,
alpha_mode: AlphaMode::Opaque, //alpha_mode: AlphaMode::Opaque,
..Default::default() ..Default::default()
}), }),
@ -59,7 +59,7 @@ fn spawn_planet(
pub struct CyberPlanetPlugin; pub struct CyberPlanetPlugin;
impl Plugin for CyberPlanetPlugin { impl Plugin for CyberPlanetPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_startup_system(spawn_planet.label(Label::Geometry)); app.add_startup_system(spawn_planet);
} }
} }
@ -86,7 +86,7 @@ fn gen_planet(sphere: Icosphere) -> (Mesh, Collider) {
.raw_points() .raw_points()
.iter() .iter()
.map(|&p| { .map(|&p| {
let disp = noise.get(p.as_dvec3().into()) as f32 * 0.04; let disp = noise.get(p.as_dvec3().into()) as f32 * 0.01;
let pt = p + (p.normalize() * disp); let pt = p + (p.normalize() * disp);
pt.into() pt.into()
}) })