85 lines
1.9 KiB
Rust
85 lines
1.9 KiB
Rust
use nannou::prelude::*;
|
||
use rayon::prelude::*;
|
||
|
||
fn main() {
|
||
nannou::app(model).update(update).simple_window(view).run();
|
||
}
|
||
|
||
#[derive(Clone)]
|
||
struct Body {
|
||
pos: DVec2,
|
||
vel: DVec2,
|
||
}
|
||
|
||
struct Model {
|
||
bodies: Vec<Body>,
|
||
}
|
||
|
||
fn model(_app: &App) -> Model {
|
||
let mut bodies = Vec::new();
|
||
|
||
let mut theta = 0.0;
|
||
for r in 0..512 {
|
||
let r = r as f64;
|
||
let r = 10.0 * r.sqrt();
|
||
|
||
bodies.push(Body {
|
||
pos: (r * theta.cos(), r * theta.sin()).into(),
|
||
vel: (0.0, 0.0).into(),
|
||
});
|
||
|
||
theta += 1.94161103873;
|
||
}
|
||
|
||
Model { bodies }
|
||
}
|
||
|
||
fn update(app: &App, model: &mut Model, _update: Update) {
|
||
const G: f64 = 6.67408e-11;
|
||
|
||
let bodies = model.bodies.clone();
|
||
let delta_t = app.duration.since_prev_update.as_secs_f64();
|
||
|
||
model
|
||
.bodies
|
||
.par_iter_mut()
|
||
.enumerate()
|
||
.for_each(|(i, body)| {
|
||
let mut acc: DVec2 = (0.0, 0.0).into();
|
||
|
||
bodies.iter().enumerate().for_each(|(j, other_body)| {
|
||
if i == j {
|
||
return;
|
||
}
|
||
|
||
let delta = other_body.pos - body.pos;
|
||
let dist_sq = body.pos.distance_squared(other_body.pos);
|
||
|
||
if dist_sq < 1.0 {
|
||
return;
|
||
}
|
||
|
||
let force = G * /* × mass_a × mass_b = */ 1e14 / dist_sq;
|
||
|
||
acc += delta * force / dist_sq.sqrt();
|
||
acc -= 0.5 * delta / (dist_sq * 0.5);
|
||
});
|
||
|
||
body.vel += acc * delta_t;
|
||
body.pos += body.vel * delta_t;
|
||
});
|
||
}
|
||
|
||
fn view(app: &App, model: &Model, frame: Frame) {
|
||
// let t = app.duration.since_start.as_secs_f64();
|
||
|
||
let draw = app.draw();
|
||
draw.background().color(BLACK);
|
||
|
||
for body in model.bodies.iter() {
|
||
draw.ellipse().w_h(10.0, 10.0).xy(body.pos.as_f32());
|
||
}
|
||
|
||
draw.to_frame(app, &frame).unwrap();
|
||
}
|