diff --git a/src/lib.rs b/src/lib.rs index aace608..21acbbf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,24 +4,24 @@ use bevy_spatial::{kdtree::KDTree3, SpatialAccess}; pub type NNTree = KDTree3; -// toid +// toid stuff const SPEED: f32 = 5.0; -const SPEED_DIFF_RANGE: f32 = 0.1; // +/- 8% +const SPEED_DIFF_RANGE: f32 = 0.1; // +/- 10% const MAX_DELTA_V: f32 = std::f32::consts::PI * 2.0; // basically 360 degrees/sec // how far from origin before really wanting to come back -const RADIUS: f32 = 400.0; +const RADIUS: f32 = 50.0; // how close to try to stay to your buddies -const BUDDY_RADIUS: f32 = 50.0; +const BUDDY_RADIUS: f32 = 30.0; -const MIN_ALTITUDE: f32 = 1.5; +const MIN_ALTITUDE: f32 = 3.5; #[derive(Debug, FromArgs, Resource)] /// Toid Watching pub struct Config { /// how many Toids to spawn - #[argh(option, short = 't', default = "100")] + #[argh(option, short = 't', default = "5_000")] pub toids: usize, } @@ -49,9 +49,9 @@ pub fn turkey_time( let speed = SPEED + (SPEED * speed_diff); let vel = unit_vec(r) * speed; let buddies = r.gen_range(6..=8); - let x = r.gen_range(-5.0..=5.0); - let z = r.gen_range(-5.0..=5.0); - let y = r.gen_range(0.1..=2.5); + let x = r.gen_range(-10.0..=10.0); + let z = r.gen_range(-10.0..=10.0); + let y = r.gen_range(0.1..=5.5); let spatial_bundle = SpatialBundle { transform: Transform::from_xyz(x, MIN_ALTITUDE + y, z), ..Default::default() @@ -86,16 +86,6 @@ pub fn update_vel( let pos = xform.translation; let original_dir = dir.clone(); - // nudge toward origin if too far - { - let dist = pos.length(); - let toward_origin = -pos.normalize(); - let rot = Quat::from_rotation_arc(dir, toward_origin); - let pct = (dist / RADIUS).min(1.0); - let rot = Quat::IDENTITY.slerp(rot, pct); - dir = rot.mul_vec3(dir).normalize(); - } - // find buddies and orient; point more towards further-away buddies for buddy in buddies.0.iter() { let bp = positions.get(buddy).unwrap_or(&pos); @@ -108,20 +98,31 @@ pub fn update_vel( } // avoid flying into neighbors + let min_dist = speed / 2.0; for neighbor in index - .within_distance(pos, speed) + .within_distance(pos, min_dist) .iter() .filter(|n| n.1.is_some() && n.1.unwrap() != entity) { let bp = neighbor.0; let bdir = pos - bp; let dist = bdir.length(); - let s = 1.0 - (dist / speed).min(1.0); + let s = 1.0 - (dist / min_dist).min(1.0); let rot = Quat::from_rotation_arc(dir, bdir.normalize()); let rot = Quat::IDENTITY.slerp(rot, s); dir = rot.mul_vec3(dir).normalize(); } + // nudge toward origin if too far + { + let dist = pos.length(); + let toward_origin = -pos.normalize(); + let s = (dist / RADIUS).min(1.0); + let rot = Quat::from_rotation_arc(dir, toward_origin); + let rot = Quat::IDENTITY.slerp(rot, s); + dir = rot.mul_vec3(dir).normalize(); + } + // nudge up if too low if pos.y < MIN_ALTITUDE { let dh = MIN_ALTITUDE - pos.y; diff --git a/src/main.rs b/src/main.rs index ba6575d..77a1346 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,21 +1,28 @@ -use bevy::prelude::*; -use bevy_spatial::{AutomaticUpdate, TransformMode}; +use std::time::Duration; use audubon::*; +use bevy::prelude::*; +use bevy_spatial::{AutomaticUpdate, TransformMode}; fn main() { let config: audubon::Config = argh::from_env(); App::new() .add_plugins(DefaultPlugins) - .add_plugins(AutomaticUpdate::::new().with_transform(TransformMode::GlobalTransform)) + .add_plugins( + AutomaticUpdate::::new() + .with_transform(TransformMode::GlobalTransform) + .with_frequency(Duration::from_millis(150)), + ) .insert_resource(config) .insert_resource(Positions::default()) + .insert_resource(ClearColor(Color::rgb(0.64, 0.745, 0.937))) // a nice light blue + .insert_resource(AmbientLight { + color: Color::WHITE, + brightness: 1.0, + }) .add_systems(Startup, setup) .add_systems(Update, (update_pos, update_buddies, update_vel).chain()) - .add_systems( - Update, - (rotate_camera, update_config, bevy::window::close_on_esc), - ) + .add_systems(Update, (rotate_camera, bevy::window::close_on_esc)) .run(); } @@ -29,12 +36,12 @@ fn setup( let rand = &mut rand::thread_rng(); commands.spawn(Camera3dBundle { - transform: Transform::from_xyz(0., 3.5, 40.).looking_at(Vec3::new(0.0, 10.0, 0.0), Vec3::Y), + transform: Transform::from_xyz(0., 5.0, 25.).looking_at(Vec3::new(0.0, 5.0, 0.0), Vec3::Y), ..default() }); // plane commands.spawn(PbrBundle { - mesh: meshes.add(Mesh::from(shape::Plane::from_size(50.0))), + mesh: meshes.add(Mesh::from(shape::Plane::from_size(500.0))), material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()), ..default() }); @@ -45,23 +52,10 @@ fn setup( let _ = turkey_time(&mut commands, &toid_model, rand); } - // light - commands.spawn(PointLightBundle { - point_light: PointLight { - intensity: 1500.0, - shadows_enabled: true, - ..default() - }, - transform: Transform::from_xyz(4.0, 8.0, 4.0), - ..default() - }); - - // example instructions + // instructions commands.spawn( TextBundle::from_section( - "Press 'D' to toggle drawing gizmos on top of everything else in the scene\n\ - Press 'P' to toggle perspective for line gizmos\n\ - Hold 'Left' or 'Right' to change the line width", + "Up and down for camera forward and back; hold shift to change height.\nLeft and right to rotate camera; hold shift to translate.\nPress 'r' to look back at the origin. Press 'ESC' to quit.", TextStyle { font_size: 20., ..default() @@ -76,27 +70,44 @@ fn setup( ); } -fn rotate_camera(mut query: Query<&mut Transform, With>, time: Res