use std::{f32::consts::PI, ops::Range};
use bevy::window::WindowResized;
use crate::{config::planet::Planet, ecs::{Me, StarguideCamera, StarguideGizmos, StarguideOrbit, StarguideOrbitImage}, prelude::*, world_config::WorldConfigResource};
use bevy::render::render_resource::Extent3d;
pub fn starguide_orbit_plugin(app: &mut App) {
app
.add_systems(Update, (update_orbits));
}
fn update_orbits(
//orbit_image: Res<StarguideOrbitImage>,
//mut images: ResMut<Assets<Image>>,
camera: Single<(&Camera, &GlobalTransform, &Projection), With<StarguideCamera>>,
me: Single<(&Transform, &LinearVelocity), (With<Me>, Without<StarguideCamera>)>,
//orbit: Single<&Transform, (With<StarguideOrbit>, Without<Me>, Without<StarguideCamera>)>,
mut gizmos: Gizmos<StarguideGizmos>,
world_config: Res<WorldConfigResource>,
planets: Query<(&Mass, &Planet, &Transform)>,
) {
/*let Some(image) = images.get_mut(&orbit_image.0) else {
error!("Orbit prediction image not found");
return
};*/
let Some(world_config) = &world_config.config else {
return;
};
let Projection::Orthographic(ref projection) = camera.2.clone() else { return };
//image.clear(&(Color::BLACK.to_srgba().to_u8_array()));
let mut p_mass = 0.0;
let mut p_transform = Transform::default();
let (sun_mass, _, sun_transform) = planets.iter().filter(|planet| planet.1.name == "Sun").next().unwrap();
for (mass, planet, transform) in planets {
if planet.name == "Sun" { continue }
let a = sun_transform.translation - transform.translation;
let hill_sphere = a.length()*(mass.0/(3.0*(sun_mass.0+mass.0))).powf(1.0/3.0);
if hill_sphere > (me.0.translation - transform.translation).length() {
p_mass = mass.0;
p_transform = *transform;
break;
}
}
if p_mass == 0.0 {
p_mass = sun_mass.0;
p_transform = *sun_transform;
}
// orbit magic
let rel_pos = me.0.translation - p_transform.translation;
let u = world_config.world.gravity*p_mass;
let h = rel_pos.x*me.1.y - rel_pos.y*me.1.x;
let r = rel_pos.length();
let a = (u*r) / (2.0*u - r*(me.1.x*me.1.x + me.1.y*me.1.y));
let e_x = rel_pos.x/r - (h*me.1.y)/u;
let e_y = rel_pos.y/r + (h*me.1.x)/u;
let f_x = -2.0*a*e_x;
let f_y = -2.0*a*e_y;
// 200 steps in the revolution
let mut first_pos = None;
let mut last_pos = None;
for i in 0..200 {
let theta = 2.0*PI*(i as f32)/200.0;
let r = (1.0/2.0) * ((f_x*f_x + f_y*f_y - 4.0*a*a) / (-2.0*a - f_x*theta.cos() - f_y*theta.sin()));
if r < 0.0 { continue }
// convert r to image coords
let pos = Vec2::new(r*theta.cos(), r*theta.sin()) + p_transform.translation.truncate();
/*let pos = pos + p_transform.translation.truncate() - orbit.translation.truncate();
let pos = Vec2::new(pos.x, -pos.y);
let pos = pos / projection.scale;
let pos = pos + image.size_f32()/2.0;*/
//if !(pos.x as u32 >= image.size().x || pos.y as u32 >= image.size().y) && i != 0 {
if last_pos.is_some() {
gizmos.line_2d(last_pos.unwrap(), pos, Color::linear_rgb(1.0, 0.0, 0.0));
}
if first_pos.is_none() { first_pos = Some(pos) }
last_pos = Some(pos);
}
if first_pos.is_some() && last_pos.is_some() {
gizmos.line_2d(first_pos.unwrap(), last_pos.unwrap(), Color::linear_rgb(1.0, 0.0, 0.0));
}
}
/*fn window_resize(
orbit_image: Res<StarguideOrbitImage>,
mut images: ResMut<Assets<Image>>,
mut resize_ev: MessageReader<WindowResized>,
camera: Single<&Camera, With<StarguideCamera>>,
) {
let Some(image) = images.get_mut(&orbit_image.0) else {
error!("Orbit prediction image not found");
return
};
for _ in resize_ev.read() {
let Some(Vec2 {x: width, y: height}) = camera.logical_viewport_size() else {
continue
};
image.resize(Extent3d {
width: width as u32,
height: height as u32,
depth_or_array_layers: 1,
});
}
}*/