use std::f32::consts::TAU; use bevy::prelude::*; use rand::prelude::*; use crate::geometry::PLANET_RADIUS; pub const LIGHT_RANGE: f32 = 50.0; #[derive(Component)] struct AnimatedCyberLight { axis: Vec3, rate: f32, } #[derive(Component)] pub(crate) struct AnimateCyberLightWireframe; fn spawn_moving_lights( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { let rng = &mut thread_rng(); // spawn orbiting bisexual lights for _ in 0..511 { // 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(500.0..900.0); let radius = rng.gen::() * 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() }; commands // first, spawn an entity with a transform we can rotate .spawn_bundle(( AnimatedCyberLight { axis, rate }, Transform::from_rotation(rotation), GlobalTransform::default(), )) .with_children(|parent| { parent // now spawn a child entity with a pointlight, and a relative transform that's // just translation from the parent .spawn_bundle(PointLightBundle { transform, point_light, ..Default::default() }) .with_children(|builder| { builder // now a simple mesh to show a wireframe. .spawn_bundle(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); }); // mesh child }); // light child } } fn spawn_static_lights( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { 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, brightness: 0.32, }); // up light commands .spawn_bundle(PointLightBundle { transform: Transform::from_xyz(0.0, PLANET_RADIUS + 30.0, 0.0), point_light: pink_light, ..Default::default() }) .with_children(|builder| { builder.spawn_bundle(PbrBundle { mesh: meshes.add(Mesh::from(shape::Icosphere { radius: 10.0, subdivisions: 2, })), material: materials.add(StandardMaterial { base_color: Color::BLUE, emissive: Color::PINK, ..Default::default() }), ..Default::default() }); }); // down light commands .spawn_bundle(PointLightBundle { transform: Transform::from_xyz(0.0, -PLANET_RADIUS - 30.0, 0.0), point_light: blue_light, ..Default::default() }) .with_children(|builder| { builder.spawn_bundle(PbrBundle { mesh: meshes.add(Mesh::from(shape::Icosphere { radius: 10.0, subdivisions: 2, })), material: materials.add(StandardMaterial { base_color: Color::PINK, emissive: Color::BLUE, ..Default::default() }), ..Default::default() }); }); } fn orbit_lights(time: Res