This commit is contained in:
Leon Liu 2025-08-13 20:50:09 +09:00
parent aa48f1fc02
commit ca2b06efb8

View File

@ -1,84 +1,162 @@
use bevy::{math::DVec3, prelude::*}; use bevy::{math::DVec3, prelude::*};
// Unit wrapper types - all distances in AU
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct DistanceAu(pub f64);
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct PositionAu(pub DVec3);
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct VelocityAuPerDay(pub DVec3);
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct MassKg(pub f64);
#[derive(Clone, Debug, PartialEq)]
pub struct ObjectName(pub String);
// Component wrappers
#[derive(Component)] #[derive(Component)]
struct PositionAu(DVec3); struct Position(PositionAu);
#[derive(Component)] #[derive(Component)]
struct VelocityAuPerDay(DVec3); struct Velocity(VelocityAuPerDay);
#[derive(Component)] #[derive(Component)]
struct MassKg(f64); struct Mass(MassKg);
#[derive(Component)] #[derive(Component)]
struct RadiusKm(f64); struct Radius(DistanceAu);
#[derive(Component)] #[derive(Component)]
struct Name(String); struct Name(ObjectName);
#[derive(Bundle)] #[derive(Bundle)]
struct ObjectBundle { struct ObjectBundle {
name: Name, name: Name,
position: PositionAu, position: Position,
mass: MassKg, mass: Mass,
radius: RadiusKm, radius: Radius,
velocity: VelocityAuPerDay, velocity: Velocity,
} }
pub struct SolarRenderingPlugin; pub struct SolarRenderingPlugin;
impl Plugin for SolarRenderingPlugin { impl Plugin for SolarRenderingPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
// Rendering systems will be added here app.add_systems(Startup, setup_rendering)
.add_systems(
FixedPostUpdate,
(sync_radius_to_mesh, sync_position_to_transform),
);
} }
} }
fn sync_radius_to_mesh(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
query: Query<(Entity, &Radius, Option<&Mesh3d>), Changed<Radius>>,
) {
for (entity, radius, existing_mesh) in query.iter() {
// Radius is already in AU, use directly for rendering
let render_radius = radius.0.0;
// Create or update sphere mesh
let sphere_mesh = meshes.add(Sphere::new(render_radius as f32));
let material = materials.add(StandardMaterial {
base_color: Color::WHITE,
..default()
});
if existing_mesh.is_none() {
// Add mesh and material components if they don't exist
commands
.entity(entity)
.insert((Mesh3d(sphere_mesh), MeshMaterial3d(material)));
} else {
// Update existing mesh
commands.entity(entity).insert(Mesh3d(sphere_mesh));
}
}
}
fn sync_position_to_transform(mut query: Query<(&Position, &mut Transform), Changed<Position>>) {
for (position, mut transform) in query.iter_mut() {
// Convert AU to rendering units (1 AU = 1 unit for simplicity)
transform.translation = position.0.0.as_vec3();
}
}
fn setup_rendering(mut commands: Commands) {
// Spawn camera positioned to view the solar system
// Place it above and to the side for a good perspective view
commands.spawn((
Camera3d::default(),
Transform::from_xyz(2.0, 1.5, 2.0).looking_at(Vec3::ZERO, Vec3::Y),
));
// Spawn directional light from the sun's position
// This simulates sunlight illuminating the planets
commands.spawn((
DirectionalLight {
color: Color::WHITE,
illuminance: 10000.0, // Bright like the sun
shadows_enabled: true,
..default()
},
Transform::from_xyz(0.0, 0.0, 0.0).looking_at(Vec3::new(1.0, 0.0, 0.0), Vec3::Y),
));
}
fn setup_solar_system(mut commands: Commands) { fn setup_solar_system(mut commands: Commands) {
// Sun - From NASA JPL Horizons data (J2000.0 epoch) // Sun - From NASA JPL Horizons data (J2000.0 epoch)
// Physical properties: Mass = 1988410 x 10^24 kg, Radius = 695700 km // Physical properties: Mass = 1988410 x 10^24 kg, Radius = 695700 km = 0.00465 AU
commands.spawn(ObjectBundle { commands.spawn(ObjectBundle {
name: Name("Sun".to_string()), name: Name(ObjectName("Sun".to_string())),
position: PositionAu(DVec3::new(0.0, 0.0, 0.0)), // At barycenter position: Position(PositionAu(DVec3::new(0.0, 0.0, 0.0))), // At barycenter
velocity: VelocityAuPerDay(DVec3::new(0.0, 0.0, 0.0)), // Stationary relative to barycenter velocity: Velocity(VelocityAuPerDay(DVec3::new(0.0, 0.0, 0.0))), // Stationary relative to barycenter
mass: MassKg(1.988410e30), // Solar mass in kg mass: Mass(MassKg(1.988410e30)), // Solar mass in kg
radius: RadiusKm(695700.0), // Solar radius in km radius: Radius(DistanceAu(0.00465)), // Solar radius in AU (695700 km / 149597870.691)
}); });
// Earth - From NASA JPL Horizons data (A.D. 2000-Jan-01 12:00:00.0000 TDB) // Earth - From NASA JPL Horizons data (A.D. 2000-Jan-01 12:00:00.0000 TDB)
// Position and velocity vectors in ecliptic J2000.0 frame relative to Sun // Position and velocity vectors in ecliptic J2000.0 frame relative to Sun
// Mass = 5.97219 x 10^24 kg, Mean radius = 6371.01 km // Mass = 5.97219 x 10^24 kg, Mean radius = 6371.01 km = 0.0000426 AU
commands.spawn(ObjectBundle { commands.spawn(ObjectBundle {
name: Name("Earth".to_string()), name: Name(ObjectName("Earth".to_string())),
position: PositionAu(DVec3::new( position: Position(PositionAu(DVec3::new(
-1.771350992727098e-1, // X = -0.177135 AU -1.771350992727098e-1, // X = -0.177135 AU
9.672416867665306e-1, // Y = 0.967242 AU 9.672416867665306e-1, // Y = 0.967242 AU
-4.085281582511366e-6, // Z = -4.085e-6 AU -4.085281582511366e-6, // Z = -4.085e-6 AU
)), ))),
velocity: VelocityAuPerDay(DVec3::new( velocity: Velocity(VelocityAuPerDay(DVec3::new(
-1.720762506872895e-2, // VX = -0.0172076 AU/day -1.720762506872895e-2, // VX = -0.0172076 AU/day
-3.158782144324866e-3, // VY = -0.00315878 AU/day -3.158782144324866e-3, // VY = -0.00315878 AU/day
1.049888594613343e-7, // VZ = 1.04989e-7 AU/day 1.049888594613343e-7, // VZ = 1.04989e-7 AU/day
)), ))),
mass: MassKg(5.97219e24), // Earth mass in kg mass: Mass(MassKg(5.97219e24)), // Earth mass in kg
radius: RadiusKm(6371.01), // Mean radius in km radius: Radius(DistanceAu(0.0000426)), // Mean radius in AU (6371.01 km / 149597870.691)
}); });
// Moon - From NASA JPL Horizons data (A.D. 2000-Jan-01 12:00:00.0000 TDB) // Moon - From NASA JPL Horizons data (A.D. 2000-Jan-01 12:00:00.0000 TDB)
// Position and velocity vectors in ecliptic J2000.0 frame relative to Sun // Position and velocity vectors in ecliptic J2000.0 frame relative to Sun
// Mass = 7.349 x 10^22 kg, Mean radius = 1737.53 km // Mass = 7.349 x 10^22 kg, Mean radius = 1737.53 km = 0.0000116 AU
commands.spawn(ObjectBundle { commands.spawn(ObjectBundle {
name: Name("Moon".to_string()), name: Name(ObjectName("Moon".to_string())),
position: PositionAu(DVec3::new( position: Position(PositionAu(DVec3::new(
-1.790843809223965e-1, // X = -0.179084 AU -1.790843809223965e-1, // X = -0.179084 AU
9.654035607264573e-1, // Y = 0.965404 AU 9.654035607264573e-1, // Y = 0.965404 AU
2.383726922995396e-4, // Z = 0.000238373 AU 2.383726922995396e-4, // Z = 0.000238373 AU
)), ))),
velocity: VelocityAuPerDay(DVec3::new( velocity: Velocity(VelocityAuPerDay(DVec3::new(
-1.683595459141215e-2, // VX = -0.0168360 AU/day -1.683595459141215e-2, // VX = -0.0168360 AU/day
-3.580960720855671e-3, // VY = -0.00358096 AU/day -3.580960720855671e-3, // VY = -0.00358096 AU/day
-6.540550604528720e-6, // VZ = -6.54055e-6 AU/day -6.540550604528720e-6, // VZ = -6.54055e-6 AU/day
)), ))),
mass: MassKg(7.349e22), // Moon mass in kg mass: Mass(MassKg(7.349e22)), // Moon mass in kg
radius: RadiusKm(1737.53), // Mean radius in km radius: Radius(DistanceAu(0.0000116)), // Mean radius in AU (1737.53 km / 149597870.691)
}); });
} }