Browse Source

Added saving/loading

master
Stephen 5 months ago
parent
commit
5c631716a0
7 changed files with 132 additions and 30 deletions
  1. +2
    -1
      .gitignore
  2. +50
    -0
      Cargo.lock
  3. +1
    -0
      Cargo.toml
  4. +74
    -27
      src/main.rs
  5. +2
    -1
      src/rigid_point.rs
  6. +1
    -0
      src/tests.rs
  7. +2
    -1
      src/vector3d.rs

+ 2
- 1
.gitignore View File

@ -1,3 +1,4 @@
/target
/.idea
/frames
/frames
/saves

+ 50
- 0
Cargo.lock View File

@ -157,6 +157,7 @@ dependencies = [
"png",
"rand",
"rayon",
"serde",
]
[[package]]
@ -244,6 +245,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
[[package]]
name = "proc-macro2"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -320,6 +339,20 @@ name = "serde"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.114"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "strsim"
@ -328,6 +361,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "syn"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@ -343,6 +387,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"


+ 1
- 0
Cargo.toml View File

@ -9,6 +9,7 @@ edition = "2018"
[dependencies]
rand = "0.7"
rayon = "1.3"
serde = { version = "1.0", features = ["derive"] }
bincode = "1.3"
png = "0.16"
clap = "2.33"


+ 74
- 27
src/main.rs View File

@ -1,7 +1,3 @@
use rand::prelude::*;
use rayon::prelude::*;
use render::Scene;
mod barnes_hut;
mod render;
mod rigid_point;
@ -9,14 +5,22 @@ mod vector3d;
use barnes_hut::Octree;
use clap::{App, AppSettings, Arg, SubCommand};
use rand::prelude::*;
use rayon::prelude::*;
use render::Scene;
use rigid_point::RigidPoint;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::{BufWriter, Read, Write};
use vector3d::Vector3D;
const G: f64 = 0.00667408;
#[derive(Serialize, Deserialize)]
struct Universe {
particles: Vec<RigidPoint>,
delta: f64,
iteration: usize,
}
impl Universe {
@ -24,19 +28,38 @@ impl Universe {
Universe {
particles: Vec::new(),
delta,
iteration: 0,
}
}
fn load(filename: &str) -> Self {
let mut buffer = Vec::new();
File::open(filename)
.unwrap()
.read_to_end(&mut buffer)
.unwrap();
bincode::deserialize(&buffer).unwrap()
}
fn push(&mut self, particle: RigidPoint) {
self.particles.push(particle);
}
fn save(&self, filename: &str) -> std::io::Result<()> {
let mut buffer = BufWriter::new(File::create(filename)?);
buffer.write_all(&bincode::serialize(self).unwrap())?;
buffer.flush()?;
Ok(())
}
}
fn main() {
let matches = App::new("3D Galaxy Simulator")
.version("0.1")
.author("Stephen D. <webmaster@scd31.com>")
.about("Simulates gravitional forces between many thousands, or millions, of stars")
.about("Simulates gravitational forces between many thousands, or millions, of stars")
.setting(AppSettings::SubcommandRequired)
.subcommand(
SubCommand::with_name("create")
@ -48,52 +71,76 @@ fn main() {
.takes_value(true),
),
)
.subcommand(
SubCommand::with_name("load")
.about("Load a previous simulation and continue it")
.arg(
Arg::with_name("filename")
.short("f")
.help("The file to load")
.takes_value(true)
.required(true),
),
)
.get_matches();
let delta = 0.005;
match matches.subcommand_name().unwrap() {
"create" => {
create_frames(10_000);
let matches = matches.subcommand_matches("create").unwrap();
let num_points: usize = matches
.value_of("num_stars")
.unwrap_or("100000")
.parse()
.unwrap_or(100_000);
println!("Starting a simulation with the following parameters: ");
println!("\tNumber of particles: {}", num_points);
println!("Generating particles...");
let mut universe = generate_random_points(delta, num_points);
println!("Done.");
create_frames(&mut universe);
}
"load" => {
let matches = matches.subcommand_matches("load").unwrap();
let file_name: &str = matches.value_of("filename").unwrap();
let mut universe = Universe::load(file_name);
create_frames(&mut universe);
}
_ => {
panic!(); /* this shouldn't ever happen */
unreachable!();
}
}
}
fn create_frames(num_iterations: usize) {
println!("Starting a simulation with the following parameters: ");
println!("Number of iterations: {}", num_iterations);
let delta = 0.005;
println!("Generating particles...");
let mut universe = generate_random_points(delta);
println!("Done.");
let mut last_percent = 0;
for iteration in 1..(num_iterations + 1) {
fn create_frames(universe: &mut Universe) {
loop {
for _ in 0..10 {
tick(&mut universe);
calc_velocities(&mut universe, delta);
tick(universe);
calc_velocities(universe, universe.delta);
}
if iteration * 100 / num_iterations != last_percent {
last_percent = iteration * 100 / num_iterations;
println!("{}% complete", last_percent);
}
println!("{}", universe.iteration);
// Create frame
let mut s = Scene::new(3840, 2160, 90.0);
for p in &universe.particles {
s.add_point_to_scene(p.position, 2000.0);
}
s.save(&format!("frames/{:04}.png", iteration));
s.save(&format!("frames/{:04}.png", universe.iteration));
// Save current iteration
match universe.save(&format!("saves/{}.gal", universe.iteration)) {
Ok(_) => {}
Err(_) => println!("Could not save current iteration!"),
};
universe.iteration += 1;
}
}
fn generate_random_points(delta: f64) -> Universe {
fn generate_random_points(delta: f64, num_points: usize) -> Universe {
let mut ret: Universe = Universe::new(delta);
let mut rng = rand::thread_rng();
for i in 0..100_000 {
for i in 0..num_points {
let radius: f64 = rng.gen_range(0.0, 50.0);
let theta: f64 = rng.gen_range(0.0, 2.0 * std::f64::consts::PI);
@ -106,7 +153,7 @@ fn generate_random_points(delta: f64) -> Universe {
position,
Vector3D::ZERO,
0.05, // mass
i,
i as isize,
0.1,
));
}


+ 2
- 1
src/rigid_point.rs View File

@ -1,6 +1,7 @@
use crate::vector3d::Vector3D;
use serde::{Deserialize, Serialize};
#[derive(Clone)]
#[derive(Clone, Serialize, Deserialize)]
pub struct RigidPoint {
pub position: Vector3D,
pub velocity: Vector3D, // Velocity is one half-timestep in the future


+ 1
- 0
src/tests.rs View File

@ -33,6 +33,7 @@ fn test_calc_gravity() {
let mut u = Universe {
particles: vec![a, b],
delta: 1.0,
iteration: 0
};
calc_velocities(&mut u, 1.0);


+ 2
- 1
src/vector3d.rs View File

@ -1,7 +1,8 @@
use serde::{Deserialize, Serialize};
use std::ops::{Add, AddAssign, Div, Mul, Sub};
// Fast vectors
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub struct Vector3D {
pub x: f64,
pub y: f64,


Loading…
Cancel
Save