added second binary - starting opengl

This commit is contained in:
Thomas Faour 2025-06-20 00:24:03 -04:00
parent 82c69b7ae1
commit 2187994616
6 changed files with 135 additions and 22 deletions

View File

@ -17,3 +17,4 @@ log = "0.4.27"
once_cell = "1.21.3"
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
bevy = "0.13"

View File

@ -21,7 +21,7 @@ Simulate the motion of celestial bodies under Newtonian gravity, with easy confi
### Prerequisites
- [Rust](https://www.rust-lang.org/tools/install) (edition 2021 or later)
- Python (optional, for animation/visualization)
- [Bevy dependencies](https://bevyengine.org/learn/book/getting-started/setup/) (for 3D visualization; see Bevy's docs for Linux requirements)
### Build
@ -29,10 +29,12 @@ Simulate the motion of celestial bodies under Newtonian gravity, with easy confi
cargo build --release
```
### Run
---
## Running the Simulator (CLI)
```bash
cargo run --release -- \
cargo run --release --bin simulator -- \
--config path/to/your_config.json \
--time 30d \
--step-size 10.0 \
@ -40,7 +42,6 @@ cargo run --release -- \
```
**Arguments:**
- `--config` (required): Path to your JSON config file with initial body states.
- `--time` (required): Total simulation time (e.g. `10s`, `5m`, `2h`, `100d`).
- `--step-size`: Simulation step size in seconds (default: `10.0`).
@ -49,10 +50,25 @@ cargo run --release -- \
---
## Running the 3D Visualizer (`orbiter`)
```bash
cargo run --release --bin orbiter
```
- Opens a 3D window with a camera and a blue sphere (placeholder for future simulation data).
- **Camera controls:**
- **Right mouse drag:** Orbit around the origin
- **Scroll wheel:** Zoom in/out
Future updates will allow loading and animating simulation output.
---
## Configuration
The config file is a JSON file describing the initial state of each body.
Examples provided in config/
Examples provided in `config/`
```json
{
@ -82,12 +98,6 @@ Examples provided in config/
---
## Animation
Coming soon.
---
## Extending
- Add more bodies or change initial conditions in the config file.
@ -105,6 +115,7 @@ MIT License
## Acknowledgments
- [Rust](https://www.rust-lang.org/)
- [Bevy](https://bevyengine.org/) for 3D visualization
- [glam](https://crates.io/crates/glam) for fast vector math
- [clap](https://crates.io/crates/clap) for CLI parsing
- [indicatif](https://crates.io/crates/indicatif) for progress bars

103
src/bin/orbiter.rs Normal file
View File

@ -0,0 +1,103 @@
use bevy::prelude::*;
use bevy::input::mouse::{MouseMotion, MouseWheel};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, (camera_orbit_controls,))
.run();
}
#[derive(Component)]
struct CameraController {
pub radius: f32,
pub theta: f32, // azimuthal angle
pub phi: f32, // polar angle
pub last_mouse_pos: Option<Vec2>,
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// Camera with controller
let radius = 30.0;
let theta = 0.0;
let phi = std::f32::consts::FRAC_PI_4;
let cam_pos = spherical_to_cartesian(radius, theta, phi);
commands.spawn((
Camera3dBundle {
transform: Transform::from_translation(cam_pos).looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
CameraController {
radius,
theta,
phi,
last_mouse_pos: None,
},
));
// Light
commands.spawn(PointLightBundle {
point_light: PointLight {
intensity: 1500.0,
shadows_enabled: true,
..default()
},
transform: Transform::from_xyz(4.0, 8.0, 4.0),
..default()
});
// Add a sphere at the origin using the new Sphere primitive
let mesh = meshes.add(Mesh::from(Sphere { radius: 1.0, ..default() }));
let material = materials.add(StandardMaterial {
base_color: Color::BLUE,
..default()
});
commands.spawn(PbrBundle {
mesh,
material,
..default()
});
}
fn spherical_to_cartesian(radius: f32, theta: f32, phi: f32) -> Vec3 {
let x = radius * phi.sin() * theta.cos();
let y = radius * phi.cos();
let z = radius * phi.sin() * theta.sin();
Vec3::new(x, y, z)
}
fn camera_orbit_controls(
mut query: Query<(&mut Transform, &mut CameraController)>,
mut mouse_motion_events: EventReader<MouseMotion>,
mut mouse_wheel_events: EventReader<MouseWheel>,
mouse_button_input: Res<ButtonInput<MouseButton>>,
windows: Query<&Window>,
) {
let window = if let Some(window) = windows.iter().next() { window } else { return; };
let mut delta = Vec2::ZERO;
for event in mouse_motion_events.read() {
delta += event.delta;
}
let mut scroll = 0.0;
for event in mouse_wheel_events.read() {
scroll += event.y;
}
for (mut transform, mut controller) in query.iter_mut() {
// Orbit (right mouse button)
if mouse_button_input.pressed(MouseButton::Right) {
let sensitivity = 0.01;
controller.theta -= delta.x * sensitivity;
controller.phi = (controller.phi - delta.y * sensitivity).clamp(0.05, std::f32::consts::PI - 0.05);
}
// Zoom
if scroll.abs() > 0.0 {
controller.radius = (controller.radius - scroll).clamp(3.0, 200.0);
}
// Update camera position
let pos = spherical_to_cartesian(controller.radius, controller.theta, controller.phi);
*transform = Transform::from_translation(pos).looking_at(Vec3::ZERO, Vec3::Y);
}
}

View File

@ -11,15 +11,10 @@ use log::{info, debug};
use indicatif::{ProgressBar, ProgressStyle};
use humantime;
// Internal modules
mod types;
mod config;
mod simulator;
// Specific uses from modules
use crate::simulator::Simulation;
use crate::types::{norm_time, real_body};
// Internal modules from the library crate
use orbital_simulator::simulation::Simulation;
use orbital_simulator::types::{norm_time, real_body};
use orbital_simulator as _; // for mod resolution
#[derive(Parser, Debug)]
#[command(
@ -50,7 +45,7 @@ struct Args {
output_file: String,
}
fn read_config<P: AsRef<Path>>(path: P) -> Result<config::ConfigFile, Box<dyn Error>> {
fn read_config<P: AsRef<Path>>(path: P) -> Result<orbital_simulator::config::ConfigFile, Box<dyn Error>> {
let file = File::open(path)?;
let reader = BufReader::new(file);
@ -119,4 +114,4 @@ fn main() {
pb.inc(args.steps_per_save as u64);
})
);
}
}

3
src/lib.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod types;
pub mod config;
pub mod simulation;