use crate::{actor, camera, nature}; use bevy::prelude::*; //use bevy::core_pipeline::Skybox; //use bevy::asset::LoadState; //use bevy::render::render_resource::{TextureViewDescriptor, TextureViewDimension}; use bevy::pbr::CascadeShadowConfigBuilder; use bevy::core_pipeline::bloom::{BloomCompositeMode, BloomSettings}; use std::f32::consts::PI; const JUPITER_SIZE: f32 = 80000.0; const ASTEROID_SIZE: f32 = 100.0; const MOON_SIZE: f32 = 200.0; const MARS_SIZE: f32 = 10.0; const ASTRONAUT_SIZE: f32 = 5.0; const PIZZERIA_SIZE: f32 = 30.0; //const SKYBOX_BRIGHTNESS: f32 = 300.0; //const SKYBOX_BRIGHTNESS_AR: f32 = 100.0; //const ASSET_CUBEMAP: &str = "textures/cubemap-fs8.png"; //const ASSET_CUBEMAP_AR: &str = "textures/out.png"; const ASSET_ASTRONAUT: &str = "external/alien.glb#Scene0"; const ASSET_ASTEROID1: &str = "models/asteroid.glb#Scene0"; const ASSET_ASTEROID2: &str = "models/asteroid2.glb#Scene0"; const ASSET_PIZZERIA: &str = "models/pizzeria.glb#Scene0"; const ASSET_JUPITER: &str = "models/jupiter.glb#Scene0"; pub struct WorldPlugin; impl Plugin for WorldPlugin { fn build(&self, app: &mut App) { app.add_systems(Startup, setup); //app.add_systems(Update, asset_loaded.after(load_cubemap_asset)); //app.add_systems(Update, swap_world_on_ar_toggle); app.insert_resource(ClearColor(Color::rgb(0.0, 0.0, 0.0))); } } #[derive(Component)] pub struct Star; //#[derive(Resource)] //pub struct WorldState { // is_loaded: bool, // entities_viewn_through_ar: bool, // cubemap_handle: Handle, // cubemap_ar_handle: Handle, //} //impl WorldState { // pub fn get_cubemap_handle(&self) -> Handle { // if self.entities_viewn_through_ar { // self.cubemap_ar_handle.clone() // } else { // self.cubemap_handle.clone() // } // } //} pub fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, mut ambient_light: ResMut, // settings: Res, asset_server: Res, ) { // let cubemap_handle = asset_server.load(ASSET_CUBEMAP); // commands.insert_resource(WorldState { // is_loaded: false, // entities_viewn_through_ar: settings.hud_active, // cubemap_handle: asset_server.load(ASSET_CUBEMAP), // cubemap_ar_handle: asset_server.load(ASSET_CUBEMAP_AR), // }); // Add player commands.spawn(( actor::Player, actor::Actor { angular_momentum: Quat::IDENTITY, ..default() }, actor::LifeForm::default(), actor::Suit { oxygen: nature::OXY_M, ..default() }, Camera3dBundle { camera: Camera { hdr: true, // HDR is required for bloom ..default() }, transform: Transform::from_xyz(0.0, 0.0, 8.0).looking_at(Vec3::ZERO, Vec3::Y), ..default() }, camera::CameraController::default(), // Skybox { // image: cubemap_handle, // brightness: SKYBOX_BRIGHTNESS, // }, BloomSettings { composite_mode: BloomCompositeMode::EnergyConserving, ..default() }, )); // Add some hand-placed asteroids let sphere_handle = meshes.add(Sphere::new(1.0)); let gray_handle = materials.add(StandardMaterial { base_color: Color::GRAY, perceptual_roughness: 1.0, ..default() }); let brown_handle = materials.add(StandardMaterial { base_color: Color::Rgba { alpha: 1.0, red: 0.8, green: 0.5, blue: 0.1 }, perceptual_roughness: 1.0, ..default() }); commands.spawn(( actor::Actor::default(), PbrBundle { mesh: sphere_handle.clone(), material: gray_handle.clone(), transform: Transform::from_xyz( 2000.0, 0.0, 0.0, ).with_scale(Vec3::splat(MOON_SIZE)), ..default() }, )); commands.spawn(( actor::Actor::default(), PbrBundle { mesh: sphere_handle.clone(), material: brown_handle.clone(), transform: Transform::from_xyz( 300.0, 40.0, 250.0, ).with_scale(Vec3::splat(MARS_SIZE)), ..default() }, )); // Generate a bunch of asteriods let maxdist = 10; for i in -maxdist..maxdist { for j in -maxdist..maxdist { for k in -maxdist..maxdist { let offset = 500.0; let dist = 8e3; let wobble = dist/2.0; let (i, j, k) = (i as f32, j as f32, k as f32); let asset = match ((i+j+k) as i32) % 2 { 0 => ASSET_ASTEROID1, _ => ASSET_ASTEROID2, }; commands.spawn(( actor::Actor { v: Vec3::new(-0.00, 0.0, 0.35), angular_momentum: Quat::from_euler(EulerRot::XYZ, 0.01, 0.01, 0.003), ..default() }, SceneBundle { transform: Transform { translation: Vec3::new( offset + dist * i + wobble * (j+k/PI).sin() * (k+j/PI).cos(), offset + dist * j + wobble * (k+i/PI).sin() * (i+k/PI).cos(), offset + dist * k + wobble * (i+j/PI).sin() * (j+i/PI).cos(), ), rotation: Quat::from_rotation_y(-PI / 3.), scale: Vec3::splat(ASTEROID_SIZE), }, scene: asset_server.load(asset), ..default() }, )); } } } // Generate starmap for star in nature::STARS { let brightness = star[3] * 2000.0; let (r, g, b) = nature::star_color_index_to_rgb(star[4]); let star_color_handle = materials.add(StandardMaterial { base_color: Color::rgb(r, g, b), emissive: Color::rgb_linear(r*brightness, g*brightness, b*brightness), ..default() }); let dist = 1e6; commands.spawn(( Star, PbrBundle { mesh: sphere_handle.clone(), material: star_color_handle.clone(), transform: Transform::from_xyz( dist * star[0], dist * star[1], dist * star[2], ) .with_scale(Vec3::splat((1000.0*star[3]).clamp(500.0, 2000.0))), ..default() } )); } // Add alien commands.spawn(( actor::Actor { v: Vec3::new(-0.05, 0.2, 0.35), ..default() }, actor::Talker { conv_id: "hialien".to_string() }, SceneBundle { transform: Transform { translation: Vec3::new( -40.0, 0.0, 40.0, ), rotation: Quat::from_rotation_y(-PI / 3.), scale: Vec3::splat(ASTRONAUT_SIZE), }, scene: asset_server.load(ASSET_ASTRONAUT), ..default() }, )); // Add pizza alien commands.spawn(( actor::Actor { v: Vec3::new(-0.05, 0.2, 0.35), angular_momentum: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0001, 0.0), ..default() }, actor::Talker { conv_id: "pizzeria".to_string() }, SceneBundle { transform: Transform { translation: Vec3::new( -2265.0, 10.0, 0.0, ), rotation: Quat::from_rotation_y(-PI / 3.), scale: Vec3::splat(ASTRONAUT_SIZE), }, scene: asset_server.load(ASSET_ASTRONAUT), ..default() }, )); // Add pizza place commands.spawn(( actor::Actor { v: Vec3::new(0.0, 0.0, 0.0), angular_momentum: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0001, 0.0), ..default() }, SceneBundle { transform: Transform { translation: Vec3::new( -2300.0, 10.0, 0.0, ), rotation: Quat::from_rotation_y(-2.0 * -PI / 2.), scale: Vec3::splat(PIZZERIA_SIZE), }, scene: asset_server.load(ASSET_PIZZERIA), ..default() }, )); commands.spawn(( actor::Actor { angular_momentum: Quat::from_euler(EulerRot::XYZ, 0.0, 0.0001, 0.0), ..default() }, SceneBundle { transform: Transform { translation: Vec3::new( 300000.0, 0.0, 500000.0, ), rotation: Quat::from_rotation_y(PI * -1.40), scale: Vec3::splat(JUPITER_SIZE), }, scene: asset_server.load(ASSET_JUPITER), ..default() }, )); // Space is DARK ambient_light.brightness = 0.0; // Add Light from the Sun commands.spawn(DirectionalLightBundle { directional_light: DirectionalLight { illuminance: 1000.0, shadows_enabled: false, ..default() }, transform: Transform::from_rotation(Quat::from_rotation_y(PI/2.0)), cascade_shadow_config: CascadeShadowConfigBuilder { first_cascade_far_bound: 7.0, maximum_distance: 25.0, ..default() } .into(), ..default() }); } //pub fn swap_world_on_ar_toggle( // asset_server: Res, // mut images: ResMut>, // mut worldstate: ResMut, // mut skyboxes: Query<&mut Skybox>, // settings: Res, //) { // if settings.hud_active != worldstate.entities_viewn_through_ar { // worldstate.is_loaded = false; // worldstate.entities_viewn_through_ar = settings.hud_active; // } // if !worldstate.is_loaded && asset_server.load_state(&worldstate.get_cubemap_handle()) == LoadState::Loaded { // let cubemap_handle = &worldstate.get_cubemap_handle(); // let image = images.get_mut(cubemap_handle).unwrap(); // if image.texture_descriptor.array_layer_count() == 1 { // image.reinterpret_stacked_2d_as_array(image.height() / image.width()); // image.texture_view_descriptor = Some(TextureViewDescriptor { // dimension: Some(TextureViewDimension::Cube), // ..default() // }); // } // // for mut skybox in &mut skyboxes { // skybox.image = cubemap_handle.clone(); // skybox.brightness = if settings.hud_active { // SKYBOX_BRIGHTNESS_AR // } else { // SKYBOX_BRIGHTNESS // } // } // // worldstate.is_loaded = true; // } //}