update
This commit is contained in:
parent
aa1ad4fbd7
commit
1e6d352e00
79
src/main.rs
79
src/main.rs
@ -1,15 +1,15 @@
|
||||
use bevy::{
|
||||
core_pipeline::{bloom::Bloom, tonemapping::Tonemapping},
|
||||
log::tracing_subscriber::field::debug,
|
||||
math::DVec3,
|
||||
prelude::*,
|
||||
window::{WindowMode, WindowResolution},
|
||||
window::WindowMode,
|
||||
};
|
||||
use bevy_inspector_egui::{bevy_egui::EguiPlugin, quick::WorldInspectorPlugin};
|
||||
use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin};
|
||||
|
||||
// Scaling factor to convert AU to game units
|
||||
// This makes the solar system larger so objects are visible at minimum camera zoom
|
||||
// Neptune is approximately 30.1 astronomical units (AU) from the Sun
|
||||
// Point light effective range is about 10 game units, so 10 game units = ~30 AU
|
||||
const AU_TO_GAME_UNITS: f64 = 0.3;
|
||||
|
||||
// Unit wrapper types - all distances in AU
|
||||
@ -160,7 +160,7 @@ fn setup_rendering(mut commands: Commands) {
|
||||
..default()
|
||||
}),
|
||||
Tonemapping::TonyMcMapface,
|
||||
Transform::from_translation(Vec3::new(2.0, 1.5, 2.0)),
|
||||
Transform::from_translation(Vec3::new(0., 0., 10.0)),
|
||||
Bloom::NATURAL,
|
||||
PanOrbitCamera {
|
||||
pan_sensitivity: 0.0, // Disable panning by setting sensitivity to 0
|
||||
@ -233,7 +233,7 @@ fn update_label_positions(
|
||||
};
|
||||
|
||||
for (mut node, label, mut text) in label_query.iter_mut() {
|
||||
if let Ok((position, name, radius)) = objects_query.get(label.target_entity) {
|
||||
if let Ok((position, name, _radius)) = objects_query.get(label.target_entity) {
|
||||
let world_pos = position.0.0 * AU_TO_GAME_UNITS;
|
||||
|
||||
if let Ok(screen_pos) = camera.world_to_viewport(camera_transform, world_pos.as_vec3())
|
||||
@ -341,6 +341,74 @@ fn setup_solar_system(mut commands: Commands) {
|
||||
));
|
||||
}
|
||||
|
||||
// High precision constants
|
||||
const G_SI: f64 = 6.67430e-11; // Gravitational constant in m³/kg/s² (2018 CODATA value)
|
||||
const AU_TO_M: f64 = 149597870691.0; // AU to meters (IAU 2012 definition, exact)
|
||||
const DAY_TO_S: f64 = 86400.0; // Day to seconds (exact)
|
||||
|
||||
// Pre-calculated G in AU³/kg/day² units for optimization
|
||||
// G_AU = G_SI * (day²/s²) / (AU³/m³)
|
||||
// G_AU = G_SI * (DAY_TO_S²) / (AU_TO_M³)
|
||||
const G_AU: f64 = G_SI * (DAY_TO_S * DAY_TO_S) / (AU_TO_M * AU_TO_M * AU_TO_M);
|
||||
|
||||
const STEPS: usize = 100;
|
||||
// Time step calculation:
|
||||
// FixedUpdate runs at 64fps, 1 game second = 7 days, 100 steps per FixedUpdate
|
||||
// DT = (7 days / 64 fps) / 100 steps = 7 / (64 * 100) = 0.00109375 days per step
|
||||
const DT: f64 = 7.0 / (64.0 * STEPS as f64); // Time step in days
|
||||
|
||||
fn n_body(mut query: Query<(&Mass, &mut Position, &mut Velocity)>) {
|
||||
// Collect all bodies data (mass, position, velocity)
|
||||
let mut bodies: Vec<(f64, DVec3, DVec3)> = query
|
||||
.iter()
|
||||
.map(|(mass, pos, vel)| (mass.0.0, pos.0.0, vel.0.0))
|
||||
.collect();
|
||||
|
||||
// Perform integration steps
|
||||
for _ in 0..STEPS {
|
||||
// Calculate forces for all bodies
|
||||
let mut forces: Vec<DVec3> = vec![DVec3::ZERO; bodies.len()];
|
||||
|
||||
for i in 0..bodies.len() {
|
||||
for j in 0..bodies.len() {
|
||||
if i != j {
|
||||
let r_vec = bodies[j].1 - bodies[i].1; // Position difference in AU
|
||||
let r_mag_au = r_vec.length();
|
||||
|
||||
if r_mag_au > 1e-10 {
|
||||
// Avoid division by zero
|
||||
// Calculate force directly in AU/day² units
|
||||
let force_magnitude =
|
||||
G_AU * bodies[i].0 * bodies[j].0 / (r_mag_au * r_mag_au);
|
||||
let acceleration = force_magnitude / bodies[i].0; // F/m = a
|
||||
let force_vec = r_vec.normalize() * acceleration;
|
||||
|
||||
forces[i] += force_vec;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update velocities and positions using Verlet integration
|
||||
for i in 0..bodies.len() {
|
||||
// Update velocity: v += a * dt
|
||||
bodies[i].2 += forces[i] * DT;
|
||||
|
||||
// Update position: x += v * dt
|
||||
let velocity = bodies[i].2;
|
||||
bodies[i].1 += velocity * DT;
|
||||
}
|
||||
}
|
||||
|
||||
// Write back updated positions and velocities
|
||||
for (i, (_mass, mut pos, mut vel)) in query.iter_mut().enumerate() {
|
||||
if let Some(body) = bodies.get(i) {
|
||||
pos.0.0 = body.1;
|
||||
vel.0.0 = body.2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins.set(WindowPlugin {
|
||||
@ -356,5 +424,6 @@ fn main() {
|
||||
.add_plugins(WorldInspectorPlugin::new())
|
||||
.add_plugins(SolarRenderingPlugin)
|
||||
.add_systems(Startup, setup_solar_system)
|
||||
.add_systems(FixedUpdate, n_body)
|
||||
.run();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user