Browse Source

Galaxy sim in 3d

master
Stephen 6 months ago
commit
5d6fb75173
4 changed files with 1792 additions and 0 deletions
  1. +1
    -0
      .gitignore
  2. +1656
    -0
      Cargo.lock
  3. +13
    -0
      Cargo.toml
  4. +122
    -0
      src/main.rs

+ 1
- 0
.gitignore View File

@ -0,0 +1 @@
/target

+ 1656
- 0
Cargo.lock
File diff suppressed because it is too large
View File


+ 13
- 0
Cargo.toml View File

@ -0,0 +1,13 @@
[package]
name = "galaxy3d"
version = "0.1.0"
authors = ["Stephen <stephen@stephendownward.ca>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
kiss3d = "0.24.1"
nalgebra = "0.21"
rand = "0.7"
rayon = "1.3"

+ 122
- 0
src/main.rs View File

@ -0,0 +1,122 @@
extern crate kiss3d;
extern crate nalgebra as na;
use na::{Vector3, UnitQuaternion, Translation3};
use kiss3d::window::Window;
use kiss3d::light::Light;
use kiss3d::scene::SceneNode;
use rand::prelude::*;
use std::time::Instant;
use rayon::prelude::*;
#[derive(Clone)]
struct RigidPoint {
position: Vector3<f32>,
velocity: Vector3<f32>,
mass: f64,
index: usize
}
impl RigidPoint {
fn new(position: Vector3<f32>, velocity: Vector3<f32>, mass: f64, index: usize) -> Self {
RigidPoint {
position: position,
velocity: velocity,
mass: mass,
index: index
}
}
fn update_node(&self, node: &mut SceneNode) {
node.set_local_translation(Translation3::from(self.position));
}
}
#[derive(Clone)]
struct Universe {
particles: Vec<RigidPoint>,
nodes: Vec<SceneNode>
}
impl Universe {
fn new() -> Self {
Universe { particles: Vec::new(), nodes: Vec::new() }
}
fn push(&mut self, particle: RigidPoint, node: SceneNode) {
self.particles.push(particle);
self.nodes.push(node)
}
}
fn main() {
println!("{}", std::mem::size_of::<RigidPoint>());
let mut window = Window::new("Galaxy simulator");
window.set_light(Light::StickToCamera);
let mut particles = generate_random_points(&mut window);
let mut start_time = Instant::now();
while window.render() {
calc_velocities(&mut particles, start_time.elapsed().as_secs_f64());
tick(&mut particles);
start_time = Instant::now();
}
}
fn generate_random_points(window: &mut Window) -> Universe {
let mut ret: Universe = Universe::new();
let mut rng = rand::thread_rng();
for i in 0..3000 {
let x: f32 = rng.gen_range(-50.0, 50.0);
let y: f32 = rng.gen_range(-50.0, 50.0);
let z: f32 = rng.gen_range(-5.0, 5.0); // Flat galaxy
let position: Vector3<f32> = Vector3::new(x, y, z);
let velocity: Vector3<f32> = Vector3::new(-z, x, y);
let node = window.add_sphere(0.1);
ret.push(RigidPoint::new(position, velocity / 1000.0, 1.0, i), node);
}
return ret;
}
const G: f32 = 0.00667408;
fn calc_velocities(u: &mut Universe, delta: f64) {
let mut p = u.particles.clone();
u.particles.par_iter_mut().for_each(|mut b| {
p.iter().for_each(|a| {
calc_gravity(&mut b, &a, delta);
});
});
}
fn calc_gravity(body: &mut RigidPoint, other: &RigidPoint, delta: f64) {
let dx = body.position.x - other.position.x;
let dy = body.position.y - other.position.y;
let dz = body.position.z - other.position.z;
let dist_squared = dx * dx + dy * dy + dz * dz;
if dist_squared < 0.01 {
// don't calculate gravity for stars that are really close
return;
}
let v = -G * (other.mass as f32) / dist_squared * delta as f32;
let hyp = dist_squared.sqrt();
body.velocity += Vector3::new(v * dx / hyp, v * dy / hyp, v * dz / hyp);
}
fn tick(u: &mut Universe) {
u.particles.par_iter_mut().for_each(|a| {
a.position += a.velocity;
});
u.particles.clone().iter().for_each(|a| {
u.nodes[a.index].set_local_translation(Translation3::from(a.position));
});
println!("tick");
}

Loading…
Cancel
Save