cyber_rider/src/lights.rs

182 lines
5.8 KiB
Rust
Raw Normal View History

2022-01-19 04:08:47 +00:00
use std::f32::consts::TAU;
use bevy::prelude::*;
2022-01-19 04:08:47 +00:00
use rand::prelude::*;
use crate::planet::PLANET_RADIUS;
2022-01-29 21:31:15 +00:00
pub const LIGHT_RANGE: f32 = 90.0;
#[derive(Component)]
2022-01-19 04:08:47 +00:00
struct AnimatedCyberLight {
axis: Vec3,
rate: f32,
}
#[derive(Component, Default)]
pub(crate) struct AnimateCyberLightWireframe {
pub wired: bool,
}
2022-01-19 23:07:24 +00:00
fn spawn_moving_lights(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
2022-01-19 04:08:47 +00:00
let rng = &mut thread_rng();
// spawn orbiting bisexual lights
for _ in 0..655 {
2022-01-19 23:07:24 +00:00
// mechanics
2022-01-20 00:02:17 +00:00
let axis = crate::random_unit_vec(rng);
2022-01-19 04:08:47 +00:00
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);
2022-01-19 23:07:24 +00:00
// 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);
2022-01-29 21:31:15 +00:00
let intensity = rng.gen_range(900.0..1300.0);
2022-01-19 23:07:24 +00:00
let radius = rng.gen::<f32>() * 2.2; // why can't this infer the gen type?
2022-01-19 04:08:47 +00:00
let point_light = PointLight {
intensity,
range: LIGHT_RANGE,
color,
2022-01-19 23:07:24 +00:00
radius: radius - 0.1,
2022-01-19 04:08:47 +00:00
shadows_enabled: true,
..Default::default()
2022-01-19 04:08:47 +00:00
};
commands
2022-01-19 23:07:24 +00:00
// first, spawn an entity with a transform we can rotate
2023-01-20 22:40:51 +00:00
.spawn((
2022-01-19 04:08:47 +00:00
AnimatedCyberLight { axis, rate },
Transform::from_rotation(rotation),
GlobalTransform::default(),
))
.with_children(|parent| {
parent
2022-01-19 23:07:24 +00:00
// now spawn a child entity with a pointlight, and a relative transform that's
// just translation from the parent
2023-01-20 22:40:51 +00:00
.spawn(PointLightBundle {
2022-01-19 04:08:47 +00:00
transform,
point_light,
..Default::default()
})
.with_children(|builder| {
builder
2022-01-19 23:07:24 +00:00
// now a simple mesh to show a wireframe.
2023-01-20 22:40:51 +00:00
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere {
radius,
subdivisions: 1,
})),
material: materials.add(StandardMaterial {
2022-01-19 23:07:24 +00:00
base_color: Color::hsla(272.0, 0.7, 0.56, 0.7),
emissive: color,
..Default::default()
}),
2022-01-19 04:08:47 +00:00
..Default::default()
})
.insert(AnimateCyberLightWireframe::default());
2022-01-19 04:08:47 +00:00
}); // mesh child
}); // light child
}
2022-01-19 23:07:24 +00:00
}
fn spawn_static_lights(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
let pink_light = PointLight {
intensity: 1_00.0,
range: LIGHT_RANGE,
color: Color::PINK,
radius: 1.0,
shadows_enabled: true,
..Default::default()
};
let blue_light = PointLight {
intensity: 1_000.0,
range: LIGHT_RANGE,
color: Color::BLUE,
radius: 1.0,
shadows_enabled: true,
..Default::default()
};
commands.insert_resource(AmbientLight {
color: Color::WHITE,
2022-02-21 21:08:49 +00:00
brightness: 0.2,
2022-01-19 23:07:24 +00:00
});
2022-01-19 04:08:47 +00:00
// up light
commands
2023-01-20 22:40:51 +00:00
.spawn(PointLightBundle {
2022-01-19 04:08:47 +00:00
transform: Transform::from_xyz(0.0, PLANET_RADIUS + 30.0, 0.0),
point_light: pink_light,
..Default::default()
})
.with_children(|builder| {
2023-01-20 22:40:51 +00:00
builder.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere {
radius: 10.0,
subdivisions: 2,
})),
material: materials.add(StandardMaterial {
2022-01-19 23:07:24 +00:00
base_color: Color::BLUE,
emissive: Color::PINK,
..Default::default()
}),
..Default::default()
});
});
// down light
commands
2023-01-20 22:40:51 +00:00
.spawn(PointLightBundle {
2022-01-19 04:08:47 +00:00
transform: Transform::from_xyz(0.0, -PLANET_RADIUS - 30.0, 0.0),
point_light: blue_light,
..Default::default()
})
.with_children(|builder| {
2023-01-20 22:40:51 +00:00
builder.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Icosphere {
radius: 10.0,
subdivisions: 2,
})),
material: materials.add(StandardMaterial {
2022-01-19 23:07:24 +00:00
base_color: Color::PINK,
emissive: Color::BLUE,
..Default::default()
}),
..Default::default()
});
});
}
2022-01-19 04:08:47 +00:00
fn orbit_lights(time: Res<Time>, mut query: Query<(&mut Transform, &AnimatedCyberLight)>) {
let dt = time.delta_seconds();
2022-01-19 04:08:47 +00:00
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);
}
}
2022-01-14 00:14:08 +00:00
pub struct CyberSpaceLightsPlugin;
impl Plugin for CyberSpaceLightsPlugin {
fn build(&self, app: &mut App) {
2022-01-19 23:07:24 +00:00
app.add_startup_system(spawn_static_lights)
.add_startup_system(spawn_moving_lights)
2022-01-19 04:08:47 +00:00
.add_system(orbit_lights);
2022-01-14 00:14:08 +00:00
}
}