Merge branch 'desert-planet'
This commit is contained in:
commit
27ba017609
File diff suppressed because it is too large
Load Diff
16
Cargo.toml
16
Cargo.toml
|
@ -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]
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
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;
|
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;
|
||||||
|
|
15
src/lib.rs
15
src/lib.rs
|
@ -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 {
|
||||||
|
|
131
src/lights.rs
131
src/lights.rs
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
23
src/main.rs
23
src/main.rs
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue