diff --git a/Cargo.lock b/Cargo.lock index ff2a540..c8f75bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,112 +2,12 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "futures" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" - -[[package]] -name = "futures-executor" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" - -[[package]] -name = "futures-macro" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" -dependencies = [ - "autocfg", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" - -[[package]] -name = "futures-task" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" - -[[package]] -name = "futures-util" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" -dependencies = [ - "autocfg", - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "proc-macro-hack", - "proc-macro-nested", - "slab", -] - [[package]] name = "getrandom" version = "0.2.3" @@ -123,7 +23,6 @@ dependencies = [ name = "hypoloop" version = "0.1.0" dependencies = [ - "futures", "rand", ] @@ -133,60 +32,12 @@ version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" -[[package]] -name = "memchr" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" - -[[package]] -name = "pin-project-lite" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - [[package]] name = "ppv-lite86" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - -[[package]] -name = "proc-macro2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - [[package]] name = "rand" version = "0.8.4" @@ -227,29 +78,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "slab" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" - -[[package]] -name = "syn" -version = "1.0.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "unicode-xid" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" - [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index bfccba6..18a2645 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,4 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -futures = "0.3.16" rand = "0.8.4" diff --git a/src/main.rs b/src/main.rs index 0980443..91cfd3c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use core::time; use std::time::{Duration, Instant}; use rand::Rng; @@ -6,129 +7,113 @@ const UPDATE_INTERVAL: u32 = 40; // debug constants const DEBUG_LOOP: bool = false; -const DEBUG_OBJECTS: bool = false; -const DEBUG_PERFORMANCE: bool = true; -const FAIL_DELAY: u32 = 50; +const DEBUG_TIME: bool = false; +const DEBUG_PARTICLES: bool = true; // scene constants +const TIMESCALE: f32 = 1.0; const GRAVITY: f32 = -9.8; -const OBJECT_COUNT: i32 = 100; +const PARTICLE_COUNT: i32 = 1; -// a struct made for physics objects +// a struct made for physics particles #[derive(Copy, Clone)] -struct PhysicsObject { +struct Particle { location: [f32; 3], velocity: [f32; 3], + acceleration: [f32; 3], gravity_enabled: bool } fn main() { let mut simulate: bool = true; - // global time - let mut time = Duration::new(0,0); + // start the clock to keep track of real time + let clock_start = Instant::now(); + + // track the end time of the last loop + let mut end_time = Instant::now(); + + // keep track of the last tick time + let mut last_tick = Instant::now(); - // track the delta time (the duration of the previous loop in milliseconds) - let mut delta_time = Duration::new(0, 0); - - // a vector of objects to calculate physics for - let mut objects: Vec = vec![]; - let mut rng = rand::thread_rng(); - for i in 0..OBJECT_COUNT { - let new_object = PhysicsObject { - location: [0.0, 0.0, 0.0], - velocity: [rng.gen::() * 10.0, rng.gen::() * 10.0, rng.gen::() * 10.0], + // a vector of particles + let mut particles: Vec = vec![]; + for i in 0..PARTICLE_COUNT { + let new_particle = Particle { + location: [0.0, 0.0, 10.0], + velocity: [0.0; 3], + acceleration: [0.0; 3], gravity_enabled: true }; - objects.push(new_object) + particles.push(new_particle) } while simulate { - // start timing the loop - let start_time = Instant::now(); - // update - if delta_time.as_millis() as u32 >= UPDATE_INTERVAL { - update(delta_time, &mut objects); - + if delta_time(last_tick) >= UPDATE_INTERVAL { // DEBUG - if DEBUG_PERFORMANCE { - let interval = delta_time.as_millis() as u32; - println!("Update interval: {}ms | Object count: {}", interval, objects.len()); - - // add more objects until it slows down enough - if interval <= UPDATE_INTERVAL { - for i in 0..10000 { - let new_object = PhysicsObject { - location: [0.0, 0.0, 0.0], - velocity: [rng.gen::() * 10.0, rng.gen::() * 10.0, rng.gen::() * 10.0], - gravity_enabled: true - }; - - objects.push(new_object) - } - } else { - // stop the simulation - simulate = false; + if DEBUG_TIME { + println!("Real time: {}ms | Delta time: {}ms", delta_time(clock_start), delta_time(last_tick)); + } + if DEBUG_PARTICLES { + for i in 0..particles.len() { + println!("Time: {}ms | Delta time: {} | Particle {} Location: {:?}, Velocity: {:?}, Acceleration: {:?}", delta_time(clock_start), delta_time(last_tick), i, particles[i].location, particles[i].velocity, particles[i].acceleration); } } - // reset the delta time - delta_time = Duration::new(0,0); - } - - //display(delta_time, &test_object); - - // update the time - let end_time = Instant::now().duration_since(start_time); - delta_time += end_time; - time += end_time; - - // DEBUG - if DEBUG_OBJECTS { - for object in objects.iter() { - println!("Time: {}s | Location: {:?} | Velocity: {:?}", time.as_millis() as f32 / 1000.0, object.location, object.velocity); - } + update(delta_time(last_tick), &mut particles); + + // record last tick time + last_tick = Instant::now(); } + + //display(delta_time, &test_particle); } } // update function // TODO - I think I'm resetting delta time in the wrong place or just using it incorrectly; frameskips aren't happening at all -fn update(delta_time: Duration, objects: &mut Vec) { +fn update(delta_time: u32, particles: &mut Vec) { if DEBUG_LOOP { println!("Updating"); } // calculate the exact timestep (fractional time in seconds) from delta time - let timestep: f32 = delta_time.as_millis() as f32 / 1000.0; + let timestep: f32 = delta_time as f32 / 1000.0; - for object in objects.iter_mut() { - // update location based on velocity + for particle in particles.iter_mut() { + // add gravitational constant to instantaneous acceleration + if particle.gravity_enabled { + // acceleration += constant + particle.acceleration[2] += GRAVITY; + } + + // update velocity + for i in 0..3 { + // velocity += timestep * acceleration + particle.velocity[i] = timestep.mul_add(particle.acceleration[i], particle.velocity[i]); + + // kill instantaneous acceleration + particle.acceleration[i] = 0.0; + } + + // update location for i in 0..3 { // location += timestep * velocity - // use an FMA here to halve the rounding error - object.location[i] = timestep.mul_add(object.velocity[i], object.location[i]); + particle.location[i] = timestep.mul_add(particle.velocity[i], particle.location[i]); } - // gravity - if object.gravity_enabled { - // velocity += timestep * gravity - // use an FMA here to halve the rounding error - object.velocity[2] = timestep.mul_add(GRAVITY, object.velocity[2]); - } - - // prevent the object from going below the ground plane, and kill downward velocity upon "hitting" the ground plane - if object.location[2] <= 0.0 { - object.location[2] = 0.0; - object.velocity[2] = object.velocity[2].max(0.0); + // prevent the particle from going below the ground plane, and kill downward velocity upon "hitting" the ground plane + if particle.location[2] <= 0.0 { + particle.location[2] = 0.0; + particle.velocity[2] = particle.velocity[2].max(0.0); } } } // render function -fn display(delta_time: Duration, object: &PhysicsObject) { +fn display(delta_time: Duration, particle: &Particle) { // calculate interpolation via delta time let interpolation: f32 = delta_time.as_millis() as f32 / UPDATE_INTERVAL as f32; @@ -138,10 +123,29 @@ fn display(delta_time: Duration, object: &PhysicsObject) { } // DEBUG - // println!("test_object | Location: {:?} | Velocity: {:?}", render_object.location, render_object.velocity); + // println!("test_particle | Location: {:?} | Velocity: {:?}", render_particle.location, render_particle.velocity); } // 1D linear interpolation fn lerp_1d(x: f64, y: f64, a: f64) -> f64 { x + ((y - x) * a) +} + +// returns a vector3 with random components +fn make_vector3() -> [f32; 3] { + let mut rng = rand::thread_rng(); + + let mut vector3: [f32; 3] = [0.0; 3]; + + for i in 0..3 { + let component = rng.gen::(); + vector3[i] = component; + } + + vector3 +} + +// gets the time in milliseconds that's elapsed since the earlier Instant +fn delta_time(earlier: Instant) -> u32 { + Instant::now().duration_since(earlier).as_millis() as u32 } \ No newline at end of file