use parallel iter to update velocities
This commit is contained in:
parent
c366dc3ec6
commit
5158fba63b
3 changed files with 86 additions and 69 deletions
BIN
assets/models/toid3.glb
Normal file
BIN
assets/models/toid3.glb
Normal file
Binary file not shown.
151
src/lib.rs
151
src/lib.rs
|
@ -1,6 +1,7 @@
|
|||
use argh::FromArgs;
|
||||
use bevy::{
|
||||
prelude::*,
|
||||
tasks::ParallelIterator,
|
||||
utils::{HashMap, HashSet},
|
||||
};
|
||||
use bevy_spatial::{kdtree::KDTree3, SpatialAccess};
|
||||
|
@ -8,7 +9,7 @@ use bevy_spatial::{kdtree::KDTree3, SpatialAccess};
|
|||
pub type NNTree = KDTree3<Toid>;
|
||||
|
||||
// toid stuff
|
||||
const SPEED: f32 = 10.0;
|
||||
const SPEED: f32 = 15.0;
|
||||
const SPEED_DIFF_RANGE: f32 = 0.1; // +/- 10%
|
||||
const MAX_DELTA_V: f32 = std::f32::consts::PI * 2.0; // basically 360 degrees/sec
|
||||
|
||||
|
@ -16,9 +17,9 @@ const MAX_DELTA_V: f32 = std::f32::consts::PI * 2.0; // basically 360 degrees/se
|
|||
const RADIUS: f32 = 50.0;
|
||||
|
||||
// how close to try to stay to your buddies
|
||||
const BUDDY_RADIUS: f32 = 10.0;
|
||||
const BUDDY_RADIUS: f32 = SPEED;
|
||||
|
||||
const MIN_ALTITUDE: f32 = 3.5;
|
||||
const MIN_ALTITUDE: f32 = 13.5;
|
||||
|
||||
#[derive(Debug, FromArgs, Resource)]
|
||||
/// Toid Watching
|
||||
|
@ -43,6 +44,9 @@ pub struct Toid {
|
|||
pub buddies: usize,
|
||||
}
|
||||
|
||||
#[derive(Resource, Debug, Deref, DerefMut, Clone, Default)]
|
||||
pub struct Paused(bool);
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Deref, DerefMut, Resource)]
|
||||
pub struct LookAt(Vec3);
|
||||
|
||||
|
@ -60,7 +64,6 @@ pub fn turkey_time(
|
|||
let y = r.gen_range(0.1..=5.5);
|
||||
let pos = Vec3::new(x, MIN_ALTITUDE + y, z);
|
||||
let xform = Transform::from_translation(pos);
|
||||
//dbg!(xform);
|
||||
let spatial_bundle = (xform, Visibility::Visible);
|
||||
commands
|
||||
.spawn(spatial_bundle)
|
||||
|
@ -68,10 +71,6 @@ pub fn turkey_time(
|
|||
.with_children(|t| {
|
||||
t.spawn(SceneRoot(scene.to_owned()))
|
||||
.insert(Transform::default());
|
||||
// .insert(Transform::from_rotation(Quat::from_axis_angle(
|
||||
// Vec3::Y,
|
||||
// -std::f32::consts::FRAC_PI_2,
|
||||
// )));
|
||||
})
|
||||
.id()
|
||||
}
|
||||
|
@ -81,72 +80,79 @@ pub fn update_vel(
|
|||
time: Res<Time>,
|
||||
positions: Res<Positions>,
|
||||
index: Res<NNTree>,
|
||||
paused: Res<Paused>,
|
||||
) {
|
||||
if **paused {
|
||||
return;
|
||||
}
|
||||
|
||||
let dt = time.delta_secs();
|
||||
let max_delta = MAX_DELTA_V * dt;
|
||||
for (xform, mut vel, toid, buddies, entity) in toids.iter_mut() {
|
||||
let speed = toid.speed;
|
||||
let mut dir = vel.normalize();
|
||||
let pos = xform.translation;
|
||||
let original_dir = dir;
|
||||
toids
|
||||
.par_iter_mut()
|
||||
.for_each(|(xform, mut vel, toid, buddies, entity)| {
|
||||
let speed = toid.speed;
|
||||
let mut dir = vel.normalize();
|
||||
let pos = xform.translation;
|
||||
let original_dir = dir;
|
||||
|
||||
// find buddies and orient; point more towards further-away buddies
|
||||
for buddy in buddies.iter() {
|
||||
let bp = positions.get(buddy).unwrap();
|
||||
let bdir = *bp - pos;
|
||||
let dist = bdir.length();
|
||||
let rot = Quat::from_rotation_arc(dir, bdir.normalize());
|
||||
let s = (dist / (BUDDY_RADIUS * 1.2)).min(1.0);
|
||||
let rot = Quat::IDENTITY.slerp(rot, s);
|
||||
dir = rot.mul_vec3(dir).normalize();
|
||||
}
|
||||
// find buddies and orient; point more towards further-away buddies
|
||||
for buddy in buddies.iter() {
|
||||
let bp = positions.get(buddy).unwrap();
|
||||
let bdir = *bp - pos;
|
||||
let dist = bdir.length();
|
||||
let rot = Quat::from_rotation_arc(dir, bdir.normalize());
|
||||
let s = (dist / (BUDDY_RADIUS * 1.2)).min(1.0);
|
||||
let rot = Quat::IDENTITY.slerp(rot, s);
|
||||
dir = rot.mul_vec3(dir).normalize();
|
||||
}
|
||||
|
||||
// avoid flying into neighbors
|
||||
let min_dist = speed * 10.0;
|
||||
for neighbor in index
|
||||
.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 / 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();
|
||||
}
|
||||
// avoid flying into neighbors
|
||||
let min_dist = speed * 20.0;
|
||||
for neighbor in index
|
||||
.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 / 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 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;
|
||||
let s = (dh / MIN_ALTITUDE).min(1.0);
|
||||
let rot = Quat::from_rotation_arc(dir, Vec3::Y);
|
||||
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;
|
||||
let s = (dh / MIN_ALTITUDE).min(1.0);
|
||||
let rot = Quat::from_rotation_arc(dir, Vec3::Y);
|
||||
let rot = Quat::IDENTITY.slerp(rot, s);
|
||||
dir = rot.mul_vec3(dir).normalize();
|
||||
}
|
||||
|
||||
// make sure velocity doesn't change too suddenly
|
||||
let delta = dir.dot(original_dir).acos();
|
||||
if delta > max_delta {
|
||||
let s = max_delta / delta;
|
||||
let rot = Quat::from_rotation_arc(original_dir, dir);
|
||||
let rot = Quat::IDENTITY.slerp(rot, s);
|
||||
dir = rot.mul_vec3(original_dir).normalize();
|
||||
}
|
||||
// make sure velocity doesn't change too suddenly
|
||||
let delta = dir.dot(original_dir).acos();
|
||||
if delta > max_delta {
|
||||
let s = max_delta / delta;
|
||||
let rot = Quat::from_rotation_arc(original_dir, dir);
|
||||
let rot = Quat::IDENTITY.slerp(rot, s);
|
||||
dir = rot.mul_vec3(original_dir).normalize();
|
||||
}
|
||||
|
||||
**vel = dir * speed;
|
||||
}
|
||||
**vel = dir * speed;
|
||||
});
|
||||
}
|
||||
|
||||
pub fn update_pos(
|
||||
|
@ -154,7 +160,12 @@ pub fn update_pos(
|
|||
mut positions: ResMut<Positions>,
|
||||
mut lookat: ResMut<LookAt>,
|
||||
time: Res<Time>,
|
||||
paused: Res<Paused>,
|
||||
) {
|
||||
if **paused {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut new_look = Vec3::ZERO;
|
||||
let dt = time.delta_secs();
|
||||
for (mut xform, vel, entity) in toids.iter_mut() {
|
||||
|
@ -204,13 +215,14 @@ pub fn update_gizmos(toids: Query<&Transform, With<Toid>>, mut gizmos: Gizmos) {
|
|||
let forward = toid.forward().as_vec3();
|
||||
let right = toid.right().as_vec3();
|
||||
gizmos.ray(pos, pos + forward, Color::srgb_u8(255, 0, 0));
|
||||
//gizmos.ray(pos, pos + up, Color::srgb_u8(0, 0, 255));
|
||||
//gizmos.ray(pos, pos + right, Color::srgb_u8(0, 255, 0));
|
||||
gizmos.ray(pos, pos + up, Color::srgb_u8(0, 0, 255));
|
||||
gizmos.ray(pos, pos + right, Color::srgb_u8(0, 255, 0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rotate_camera(
|
||||
mut query: Query<&mut Transform, With<Camera>>,
|
||||
mut paused: ResMut<Paused>,
|
||||
keys: Res<ButtonInput<KeyCode>>,
|
||||
lookat: Res<LookAt>,
|
||||
) {
|
||||
|
@ -219,6 +231,11 @@ pub fn rotate_camera(
|
|||
let forward = xform.forward() * 0.7;
|
||||
let right = xform.right().as_vec3();
|
||||
|
||||
if keys.just_pressed(KeyCode::Space) {
|
||||
let pause = **paused;
|
||||
**paused = !pause;
|
||||
}
|
||||
|
||||
if keys.pressed(KeyCode::ArrowRight) {
|
||||
xform.translation += right;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ use std::time::Duration;
|
|||
|
||||
use audubon::*;
|
||||
use bevy::{
|
||||
color::palettes::css::BLACK,
|
||||
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
|
||||
prelude::*,
|
||||
};
|
||||
|
@ -27,9 +26,10 @@ fn main() {
|
|||
brightness: 1.0,
|
||||
})
|
||||
.insert_resource(LookAt::default())
|
||||
.insert_resource(Paused::default())
|
||||
.add_systems(Startup, (setup, setup_ambient_light))
|
||||
//.add_systems(Update, update_gizmos)
|
||||
.add_systems(Update, (update_pos, update_buddies, update_vel).chain())
|
||||
.add_systems(Update, (update_pos, update_buddies, update_vel))
|
||||
.add_systems(Update, (rotate_camera, close_on_esc))
|
||||
.run();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue