Merge branch 'desert-planet'
This commit is contained in:
commit
27ba017609
16 changed files with 799 additions and 785 deletions
1055
Cargo.lock
generated
1055
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
16
Cargo.toml
16
Cargo.toml
|
@ -5,31 +5,33 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
rand = "0.8"
|
||||
bevy_polyline = "0.4"
|
||||
# bevy_polyline = "0.4"
|
||||
noise = { git = "https://github.com/Razaekel/noise-rs" }
|
||||
hexasphere = "7"
|
||||
wgpu = "0.14"
|
||||
bevy-inspector-egui = "0.17.0"
|
||||
# wgpu = "0.12"
|
||||
wgpu = "0.15"
|
||||
bevy-inspector-egui = "0.18"
|
||||
|
||||
[features]
|
||||
inspector = []
|
||||
|
||||
[dependencies.bevy]
|
||||
version = "0.9"
|
||||
version = "0.10"
|
||||
default-features = false
|
||||
features = [
|
||||
"bevy_gilrs",
|
||||
"bevy_winit",
|
||||
"render",
|
||||
"png",
|
||||
"hdr",
|
||||
"x11",
|
||||
"bevy_ui",
|
||||
"bevy_text",
|
||||
"bevy_gltf",
|
||||
"bevy_sprite",
|
||||
]
|
||||
|
||||
[dependencies.bevy_rapier3d]
|
||||
features = ["debug-render-3d"]
|
||||
version = "0.20"
|
||||
version = "0.21"
|
||||
|
||||
# Maybe also enable only a small amount of optimization for our code:
|
||||
[profile.dev]
|
||||
|
|
|
@ -46,14 +46,12 @@ impl Default for Tunneling {
|
|||
pub struct MovementSettings {
|
||||
pub accel: f32,
|
||||
pub gravity: f32,
|
||||
pub sensitivity: f32,
|
||||
}
|
||||
|
||||
impl Default for MovementSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
sensitivity: 6.0,
|
||||
accel: 40.0,
|
||||
accel: 20.0,
|
||||
gravity: 9.8,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use bevy::{
|
||||
diagnostic::FrameTimeDiagnosticsPlugin,
|
||||
prelude::{App, IntoSystemDescriptor, Plugin, ReflectResource, Resource},
|
||||
ecs::reflect::ReflectResource,
|
||||
prelude::{App, IntoSystemConfigs, Plugin, Resource},
|
||||
reflect::Reflect,
|
||||
};
|
||||
use bevy_rapier3d::prelude::{NoUserData, RapierPhysicsPlugin};
|
||||
|
@ -28,19 +29,19 @@ impl Plugin for CyberActionPlugin {
|
|||
.register_type::<CyberLean>()
|
||||
.register_type::<CatControllerSettings>()
|
||||
.add_plugin(RapierPhysicsPlugin::<NoUserData>::default())
|
||||
.add_startup_system(timestep_setup)
|
||||
.add_plugin(FrameTimeDiagnosticsPlugin::default())
|
||||
.add_system(surface_fix.label("surface_fix"))
|
||||
.add_system(gravity.label("gravity").before("cat"))
|
||||
.add_system(cyber_lean.before("cat").after("gravity"))
|
||||
.add_system(falling_cat.label("cat"))
|
||||
.add_system(input_forces.label("iforces").after("cat"))
|
||||
.add_system(
|
||||
tunnel_out
|
||||
.label("tunnel")
|
||||
.before("surface_fix")
|
||||
.after("drag"),
|
||||
)
|
||||
.add_system(surface_fix.label("surface_fix").after("cat"))
|
||||
.add_system(drag.label("drag").after("iforces"));
|
||||
.add_systems(
|
||||
(
|
||||
gravity,
|
||||
cyber_lean,
|
||||
falling_cat,
|
||||
input_forces,
|
||||
drag,
|
||||
tunnel_out,
|
||||
surface_fix,
|
||||
)
|
||||
.chain(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@ use bevy::prelude::{
|
|||
};
|
||||
use bevy_rapier3d::prelude::{
|
||||
CollisionGroups, ExternalForce, Group, MultibodyJoint, QueryFilter, RapierConfiguration,
|
||||
RapierContext, ReadMassProperties, Velocity,
|
||||
RapierContext, ReadMassProperties, TimestepMode, Velocity,
|
||||
};
|
||||
|
||||
#[cfg(feature = "inspector")]
|
||||
use super::ActionDebugInstant;
|
||||
use super::{CatControllerSettings, CatControllerState, CyberLean, MovementSettings, Tunneling};
|
||||
use crate::{
|
||||
bike::{CyberBikeBody, CyberSteering, CyberWheel, BIKE_WHEEL_COLLISION_GROUP},
|
||||
bike::{CyberBikeBody, CyberSteering, CyberWheel, WheelConfig, BIKE_WHEEL_COLLISION_GROUP},
|
||||
input::InputState,
|
||||
};
|
||||
|
||||
|
@ -27,7 +27,7 @@ fn yaw_to_angle(yaw: f32) -> f32 {
|
|||
|
||||
fn rotate_point(pt: &Vec3, rot: &Quat) -> Vec3 {
|
||||
// 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);
|
||||
// p' = rot^-1 * 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])
|
||||
}
|
||||
|
||||
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.
|
||||
pub(super) fn gravity(
|
||||
mut query: Query<(&Transform, &mut ExternalForce), With<CyberBikeBody>>,
|
||||
settings: Res<MovementSettings>,
|
||||
mut rapier_config: ResMut<RapierConfiguration>,
|
||||
#[cfg(feature = "inspector")] mut debug_instant: ResMut<ActionDebugInstant>,
|
||||
) {
|
||||
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;
|
||||
forces.force = Vec3::ZERO;
|
||||
forces.torque = Vec3::ZERO;
|
||||
|
@ -80,7 +98,6 @@ pub(super) fn falling_cat(
|
|||
time: Res<Time>,
|
||||
settings: Res<CatControllerSettings>,
|
||||
lean: Res<CyberLean>,
|
||||
#[cfg(feature = "inspector")] mut debug_instant: ResMut<ActionDebugInstant>,
|
||||
) {
|
||||
let (xform, mut forces, mut control_vars) = bike_query.single_mut();
|
||||
let world_up = xform.translation.normalize();
|
||||
|
@ -100,13 +117,6 @@ pub(super) fn falling_cat(
|
|||
if mag.is_finite() {
|
||||
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);
|
||||
*forces += force;
|
||||
|
||||
// brake
|
||||
// brake + thrust
|
||||
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
|
||||
.data
|
||||
.as_revolute_mut()
|
||||
.unwrap()
|
||||
.set_motor_max_force(factor)
|
||||
.set_motor_velocity(0.0, factor))
|
||||
.set_motor_velocity(speed, factor))
|
||||
.into();
|
||||
}
|
||||
|
||||
|
@ -159,23 +174,31 @@ pub(super) fn surface_fix(
|
|||
(Entity, &Transform, &mut CollisionGroups),
|
||||
(With<CyberWheel>, Without<Tunneling>),
|
||||
>,
|
||||
span_query: Query<&Transform, With<CyberWheel>>,
|
||||
config: Res<WheelConfig>,
|
||||
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() {
|
||||
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(
|
||||
xform.translation,
|
||||
ray_dir,
|
||||
10.0,
|
||||
config.radius * 1.1,
|
||||
false,
|
||||
QueryFilter::only_fixed(),
|
||||
) {
|
||||
cgroups.memberships = Group::NONE;
|
||||
cgroups.filters = Group::NONE;
|
||||
commands.entity(entity).insert(Tunneling {
|
||||
frames: 10,
|
||||
dir: -hit.1.normal,
|
||||
frames: 3,
|
||||
dir: hit.1.normal,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ pub(super) fn spawn_cyberbike(
|
|||
wheel_conf: Res<WheelConfig>,
|
||||
mut meshterials: Meshterial,
|
||||
) {
|
||||
let altitude = PLANET_RADIUS - 180.0;
|
||||
let altitude = PLANET_RADIUS - 10.0;
|
||||
|
||||
let mut xform = Transform::from_translation(Vec3::X * altitude)
|
||||
.with_rotation(Quat::from_axis_angle(Vec3::Z, -89.0f32.to_radians()));
|
||||
|
@ -55,7 +55,7 @@ pub(super) fn spawn_cyberbike(
|
|||
.spawn(RigidBody::Dynamic)
|
||||
.insert(spatialbundle)
|
||||
.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,
|
||||
mass_properties,
|
||||
damping,
|
||||
|
|
|
@ -22,6 +22,7 @@ pub struct WheelConfig {
|
|||
pub stiffness: f32,
|
||||
pub damping: f32,
|
||||
pub radius: f32,
|
||||
pub thickness: f32,
|
||||
pub friction: f32,
|
||||
pub restitution: f32,
|
||||
pub density: f32,
|
||||
|
@ -36,10 +37,11 @@ impl Default for WheelConfig {
|
|||
limits: [-0.5, 0.1],
|
||||
stiffness: 50.0,
|
||||
damping: 8.0,
|
||||
radius: 0.3,
|
||||
radius: 0.38,
|
||||
thickness: 0.2,
|
||||
friction: 1.2,
|
||||
restitution: 0.8,
|
||||
density: 0.6,
|
||||
restitution: 0.95,
|
||||
density: 0.9,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@ mod body;
|
|||
mod components;
|
||||
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;
|
||||
|
||||
pub(crate) use self::components::*;
|
||||
|
@ -21,6 +23,6 @@ impl Plugin for CyberBikePlugin {
|
|||
fn build(&self, app: &mut App) {
|
||||
app.insert_resource(WheelConfig::default())
|
||||
.register_type::<WheelConfig>()
|
||||
.add_startup_system_to_stage(StartupStage::PostStartup, spawn_cyberbike);
|
||||
.add_startup_system(spawn_cyberbike.in_base_set(StartupSet::PostStartup));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ pub fn spawn_tires(
|
|||
let wheels_collision_group = CollisionGroups::new(membership, filter);
|
||||
let wheel_y = conf.y;
|
||||
let wheel_rad = conf.radius;
|
||||
let _tire_thickness = conf.thickness;
|
||||
let stiffness = conf.stiffness;
|
||||
let not_sleeping = Sleeping::disabled();
|
||||
let ccd = Ccd { enabled: true };
|
||||
|
@ -28,6 +29,7 @@ pub fn spawn_tires(
|
|||
radius: wheel_rad,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let material = StandardMaterial {
|
||||
base_color: Color::Rgba {
|
||||
red: 0.01,
|
||||
|
@ -74,6 +76,7 @@ pub fn spawn_tires(
|
|||
linear_damping: 0.8,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let wheel_collider = Collider::ball(wheel_rad);
|
||||
let mass_props = ColliderMassProperties::Density(conf.density);
|
||||
let damping = conf.damping;
|
||||
|
@ -97,7 +100,7 @@ pub fn spawn_tires(
|
|||
|
||||
let axel_parent_entity = if let Some(steering) = steering {
|
||||
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 = commands
|
||||
.spawn(RigidBody::Dynamic)
|
||||
|
@ -110,24 +113,29 @@ pub fn spawn_tires(
|
|||
fork_rb_entity
|
||||
};
|
||||
|
||||
let revolute_builder = RevoluteJointBuilder::new(Vec3::X);
|
||||
let axel_joint = MultibodyJoint::new(axel_parent_entity, revolute_builder);
|
||||
let axel_builder = RevoluteJointBuilder::new(Vec3::X);
|
||||
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((
|
||||
wheel_collider,
|
||||
mass_props,
|
||||
wheel_damping,
|
||||
ccd,
|
||||
not_sleeping,
|
||||
axel_joint,
|
||||
wheels_collision_group,
|
||||
friction,
|
||||
CyberWheel,
|
||||
ExternalForce::default(),
|
||||
Restitution::new(conf.restitution),
|
||||
SpatialBundle::default(),
|
||||
TransformInterpolation::default(),
|
||||
RigidBody::Dynamic,
|
||||
));
|
||||
commands
|
||||
.spawn(pbr_bundle.clone())
|
||||
.insert((
|
||||
wheel_collider,
|
||||
mass_props,
|
||||
wheel_damping,
|
||||
ccd,
|
||||
not_sleeping,
|
||||
axel_joint,
|
||||
wheels_collision_group,
|
||||
friction,
|
||||
CyberWheel,
|
||||
ExternalForce::default(),
|
||||
Restitution::new(conf.restitution),
|
||||
TransformInterpolation::default(),
|
||||
RigidBody::Dynamic,
|
||||
))
|
||||
.insert(SpatialBundle::default());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ use crate::{bike::CyberBikeBody, input::InputState};
|
|||
// 85 degrees in radians
|
||||
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 {
|
||||
#[default]
|
||||
Hero,
|
||||
Debug,
|
||||
}
|
||||
|
@ -42,15 +43,32 @@ fn setup_cybercams(mut commands: Commands) {
|
|||
fov: std::f32::consts::FRAC_PI_3,
|
||||
..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
|
||||
.spawn(Camera3dBundle {
|
||||
projection: bevy::render::camera::Projection::Perspective(hero_projection),
|
||||
..Default::default()
|
||||
})
|
||||
.insert(fog_settings.clone())
|
||||
.insert(CyberCameras::Hero);
|
||||
|
||||
commands
|
||||
.spawn(Camera3dBundle::default())
|
||||
.insert(fog_settings)
|
||||
.insert(CyberCameras::Debug);
|
||||
}
|
||||
|
||||
|
@ -99,7 +117,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.current()) {
|
||||
if cyber.eq(&state.0) {
|
||||
cam.is_active = true;
|
||||
} else {
|
||||
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) {
|
||||
let new_state = state.current().next();
|
||||
let new_state = state.0.next();
|
||||
info!("{:?}", new_state);
|
||||
state.set(new_state).unwrap();
|
||||
next.set(new_state);
|
||||
keys.reset(KeyCode::D);
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +149,7 @@ impl Plugin for CyberCamPlugin {
|
|||
fn common(app: &mut bevy::prelude::App) {
|
||||
app.insert_resource(DebugCamOffset::default())
|
||||
.add_startup_system(setup_cybercams)
|
||||
.add_state(CyberCameras::Hero)
|
||||
.add_state::<CyberCameras>()
|
||||
.add_system(cycle_cam_state)
|
||||
.add_system(update_active_camera)
|
||||
.add_system(follow_cyberbike);
|
||||
|
|
|
@ -1,80 +1,13 @@
|
|||
use bevy::{
|
||||
prelude::*,
|
||||
render::mesh::{Indices, VertexAttributeValues},
|
||||
};
|
||||
use bevy_polyline::prelude::{Polyline, PolylineBundle, PolylineMaterial, PolylinePlugin};
|
||||
use rand::{thread_rng, Rng};
|
||||
use bevy::prelude::{App, Color, Plugin};
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
pub struct CyberGlamorPlugin;
|
||||
impl Plugin for CyberGlamorPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
#[cfg(feature = "inspector")]
|
||||
{
|
||||
use bevy_rapier3d::render::{
|
||||
DebugRenderMode, DebugRenderStyle, RapierDebugRenderPlugin,
|
||||
|
@ -97,9 +30,5 @@ impl Plugin for CyberGlamorPlugin {
|
|||
|
||||
app.add_plugin(rplugin);
|
||||
}
|
||||
|
||||
app.add_startup_system_to_stage(StartupStage::PostStartup, wireframe_planet)
|
||||
.add_system(wireframify_lights)
|
||||
.add_plugin(PolylinePlugin);
|
||||
}
|
||||
}
|
||||
|
|
65
src/input.rs
65
src/input.rs
|
@ -1,4 +1,8 @@
|
|||
use bevy::{prelude::*, utils::HashSet};
|
||||
use bevy::{
|
||||
input::gamepad::{GamepadAxisChangedEvent, GamepadButtonChangedEvent, GamepadEvent},
|
||||
prelude::*,
|
||||
utils::HashSet,
|
||||
};
|
||||
|
||||
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>) {
|
||||
for GamepadEvent {
|
||||
gamepad: _,
|
||||
event_type: ev,
|
||||
} in events.iter()
|
||||
{
|
||||
match *ev {
|
||||
GamepadEventType::ButtonChanged(GamepadButtonType::RightTrigger2, val) => {
|
||||
istate.throttle = val;
|
||||
}
|
||||
GamepadEventType::ButtonChanged(GamepadButtonType::LeftTrigger2, val) => {
|
||||
istate.throttle = -val;
|
||||
}
|
||||
GamepadEventType::ButtonChanged(GamepadButtonType::East, val) => {
|
||||
if val > 0.5 {
|
||||
istate.brake = true;
|
||||
} else {
|
||||
istate.brake = false;
|
||||
for pad_event in events.iter() {
|
||||
match pad_event {
|
||||
GamepadEvent::Button(button_event) => {
|
||||
let GamepadButtonChangedEvent {
|
||||
button_type, value, ..
|
||||
} = button_event;
|
||||
match button_type {
|
||||
GamepadButtonType::RightTrigger2 => istate.throttle = *value,
|
||||
GamepadButtonType::LeftTrigger2 => istate.throttle = -value,
|
||||
GamepadButtonType::East => {
|
||||
if value > &0.5 {
|
||||
istate.brake = true;
|
||||
} else {
|
||||
istate.brake = false;
|
||||
}
|
||||
}
|
||||
_ => info!("unhandled button press: {button_event:?}"),
|
||||
}
|
||||
}
|
||||
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickX, val) => {
|
||||
istate.yaw = val;
|
||||
}
|
||||
// ignore spurious vertical movement for now
|
||||
GamepadEventType::AxisChanged(GamepadAxisType::LeftStickY, val) => {
|
||||
istate.pitch = val;
|
||||
}
|
||||
_ => {
|
||||
info!("unhandled gamepad event: {:?}", ev);
|
||||
GamepadEvent::Axis(axis_event) => {
|
||||
let GamepadAxisChangedEvent {
|
||||
axis_type, value, ..
|
||||
} = axis_event;
|
||||
match axis_type {
|
||||
GamepadAxisType::LeftStickX => {
|
||||
istate.yaw = *value;
|
||||
}
|
||||
GamepadAxisType::RightStickY => {
|
||||
istate.pitch = *value;
|
||||
}
|
||||
_ => info!("unhandled axis event: {axis_event:?}"),
|
||||
}
|
||||
}
|
||||
GamepadEvent::Connection(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
//dbg!(&istate);
|
||||
}
|
||||
|
||||
pub struct CyberInputPlugin;
|
||||
|
|
15
src/lib.rs
15
src/lib.rs
|
@ -1,6 +1,7 @@
|
|||
use bevy::{
|
||||
ecs::schedule::StageLabel,
|
||||
prelude::{ResMut, SystemLabel, Vec3, Windows},
|
||||
ecs::schedule::SystemSet,
|
||||
prelude::{Query, Vec3, Window, With},
|
||||
window::PrimaryWindow,
|
||||
};
|
||||
|
||||
pub mod action;
|
||||
|
@ -12,7 +13,7 @@ pub mod lights;
|
|||
pub mod planet;
|
||||
pub mod ui;
|
||||
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq, SystemLabel, StageLabel)]
|
||||
#[derive(Clone, Debug, Hash, PartialEq, Eq, SystemSet)]
|
||||
pub enum Label {
|
||||
Geometry,
|
||||
Glamor,
|
||||
|
@ -20,10 +21,10 @@ pub enum Label {
|
|||
Action,
|
||||
}
|
||||
|
||||
pub fn disable_mouse_trap(mut windows: ResMut<Windows>) {
|
||||
let window = windows.get_primary_mut().unwrap();
|
||||
window.set_cursor_grab_mode(bevy::window::CursorGrabMode::None);
|
||||
window.set_cursor_visibility(true);
|
||||
pub fn disable_mouse_trap(mut window: Query<&mut Window, With<PrimaryWindow>>) {
|
||||
let mut window = window.get_single_mut().unwrap();
|
||||
window.cursor.grab_mode = bevy::window::CursorGrabMode::None;
|
||||
window.cursor.visible = true;
|
||||
}
|
||||
|
||||
pub fn random_unit_vec(r: &mut impl rand::prelude::Rng) -> Vec3 {
|
||||
|
|
131
src/lights.rs
131
src/lights.rs
|
@ -1,96 +1,9 @@
|
|||
use std::f32::consts::TAU;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use rand::prelude::*;
|
||||
use bevy::{pbr::CascadeShadowConfigBuilder, prelude::*};
|
||||
|
||||
use crate::planet::PLANET_RADIUS;
|
||||
|
||||
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(
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
|
@ -119,6 +32,13 @@ fn spawn_static_lights(
|
|||
brightness: 0.2,
|
||||
});
|
||||
|
||||
let _cascade_shadow_config = CascadeShadowConfigBuilder {
|
||||
first_cascade_far_bound: 0.3,
|
||||
maximum_distance: 3.0,
|
||||
..default()
|
||||
}
|
||||
.build();
|
||||
|
||||
// up light
|
||||
commands
|
||||
.spawn(PointLightBundle {
|
||||
|
@ -128,10 +48,13 @@ fn spawn_static_lights(
|
|||
})
|
||||
.with_children(|builder| {
|
||||
builder.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
||||
radius: 10.0,
|
||||
subdivisions: 2,
|
||||
})),
|
||||
mesh: meshes.add(
|
||||
Mesh::try_from(shape::Icosphere {
|
||||
radius: 10.0,
|
||||
subdivisions: 2,
|
||||
})
|
||||
.unwrap(),
|
||||
),
|
||||
material: materials.add(StandardMaterial {
|
||||
base_color: Color::BLUE,
|
||||
emissive: Color::PINK,
|
||||
|
@ -149,10 +72,13 @@ fn spawn_static_lights(
|
|||
})
|
||||
.with_children(|builder| {
|
||||
builder.spawn(PbrBundle {
|
||||
mesh: meshes.add(Mesh::from(shape::Icosphere {
|
||||
radius: 10.0,
|
||||
subdivisions: 2,
|
||||
})),
|
||||
mesh: meshes.add(
|
||||
Mesh::try_from(shape::Icosphere {
|
||||
radius: 10.0,
|
||||
subdivisions: 2,
|
||||
})
|
||||
.unwrap(),
|
||||
),
|
||||
material: materials.add(StandardMaterial {
|
||||
base_color: Color::PINK,
|
||||
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;
|
||||
impl Plugin for CyberSpaceLightsPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_startup_system(spawn_static_lights)
|
||||
.add_startup_system(spawn_moving_lights)
|
||||
.add_system(orbit_lights);
|
||||
app.add_startup_system(spawn_static_lights);
|
||||
}
|
||||
}
|
||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -1,27 +1,27 @@
|
|||
use bevy::prelude::*;
|
||||
#[cfg(feature = "inspector")]
|
||||
use cyber_rider::glamor::CyberGlamorPlugin;
|
||||
use cyber_rider::{
|
||||
action::CyberActionPlugin, bike::CyberBikePlugin, camera::CyberCamPlugin, disable_mouse_trap,
|
||||
glamor::CyberGlamorPlugin, input::CyberInputPlugin, lights::CyberSpaceLightsPlugin,
|
||||
planet::CyberPlanetPlugin, ui::CyberUIPlugin,
|
||||
input::CyberInputPlugin, lights::CyberSpaceLightsPlugin, planet::CyberPlanetPlugin,
|
||||
ui::CyberUIPlugin,
|
||||
};
|
||||
|
||||
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.07, 0.001, 0.02);
|
||||
const CYBER_SKY: Color = Color::rgb(0.64, 0.745, 0.937); // a light blue sky
|
||||
|
||||
fn main() {
|
||||
let mut app = App::new();
|
||||
app.insert_resource(Msaa { samples: 4 })
|
||||
app.insert_resource(Msaa::Sample4)
|
||||
.insert_resource(ClearColor(CYBER_SKY))
|
||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||
window: WindowDescriptor {
|
||||
width: 2560.0,
|
||||
height: 1440.0,
|
||||
primary_window: Some(Window {
|
||||
resolution: (2560.0, 1440.0).into(),
|
||||
..Default::default()
|
||||
},
|
||||
}),
|
||||
..Default::default()
|
||||
}))
|
||||
.add_plugin(CyberPlanetPlugin)
|
||||
.add_plugin(CyberGlamorPlugin)
|
||||
.add_plugin(CyberInputPlugin)
|
||||
.add_plugin(CyberActionPlugin)
|
||||
.add_plugin(CyberCamPlugin)
|
||||
|
@ -31,5 +31,8 @@ fn main() {
|
|||
.add_startup_system(disable_mouse_trap)
|
||||
.add_system(bevy::window::close_on_esc);
|
||||
|
||||
#[cfg(feature = "inspector")]
|
||||
app.add_plugin(CyberGlamorPlugin);
|
||||
|
||||
app.run();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use wgpu::PrimitiveTopology;
|
|||
|
||||
use crate::Label;
|
||||
|
||||
pub const PLANET_RADIUS: f32 = 6000.0;
|
||||
pub const PLANET_RADIUS: f32 = 3_000.0;
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct CyberPlanet;
|
||||
|
@ -19,7 +19,7 @@ fn spawn_planet(
|
|||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
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 {
|
||||
radius: PLANET_RADIUS,
|
||||
subdivisions: 88,
|
||||
|
@ -43,9 +43,9 @@ fn spawn_planet(
|
|||
mesh: meshes.add(mesh),
|
||||
material: materials.add(StandardMaterial {
|
||||
base_color: color,
|
||||
metallic: 0.1,
|
||||
metallic: 0.3,
|
||||
perceptual_roughness: 0.3,
|
||||
alpha_mode: AlphaMode::Opaque,
|
||||
//alpha_mode: AlphaMode::Opaque,
|
||||
..Default::default()
|
||||
}),
|
||||
|
||||
|
@ -59,7 +59,7 @@ fn spawn_planet(
|
|||
pub struct CyberPlanetPlugin;
|
||||
impl Plugin for CyberPlanetPlugin {
|
||||
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()
|
||||
.iter()
|
||||
.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);
|
||||
pt.into()
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue