use std::{f32::consts::PI, ops::Range}; use bevy::window::WindowResized; use crate::{config::planet::Planet, ecs::{Me, StarguideCamera, 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, //mut images: ResMut>, camera: Single<(&Camera, &GlobalTransform, &Projection), With>, me: Single<(&Transform, &LinearVelocity), (With, Without)>, //orbit: Single<&Transform, (With, Without, Without)>, mut gizmos: Gizmos, world_config: Res, 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 last_pos = Vec2::ZERO; 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())); // 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 i != 0 { gizmos.line_2d(last_pos, pos, Color::linear_rgb(1.0, 0.0, 0.0)); } last_pos = pos; } } /*fn window_resize( orbit_image: Res, mut images: ResMut>, mut resize_ev: MessageReader, camera: Single<&Camera, With>, ) { 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, }); } }*/