diff --git a/Cargo.lock b/Cargo.lock index 047b365..ff2a540 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ 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" @@ -102,13 +108,31 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "hypoloop" version = "0.1.0" dependencies = [ "futures", + "rand", ] +[[package]] +name = "libc" +version = "0.2.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" + [[package]] name = "memchr" version = "2.4.0" @@ -127,6 +151,12 @@ 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" @@ -157,6 +187,46 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + [[package]] name = "slab" version = "0.4.3" @@ -179,3 +249,9 @@ 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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/Cargo.toml b/Cargo.toml index 04a9b30..bfccba6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,5 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -futures = "0.3.16" \ No newline at end of file +futures = "0.3.16" +rand = "0.8.4" diff --git a/src/main.rs b/src/main.rs index 1ca03fb..dc1144d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ use std::time::{Duration, Instant}; +use rand::Rng; // loop constants const UPDATE_INTERVAL: u32 = 40; @@ -8,8 +9,9 @@ const DEBUG_LOOP: bool = false; const GRAVITY: f32 = -9.8; // a struct made for physics objects -#[derive(Copy, Clone)] +#[derive(Clone)] struct PhysicsObject { + name: String, location: [f32; 3], velocity: [f32; 3], gravity_enabled: bool @@ -17,19 +19,26 @@ struct PhysicsObject { fn main() { let mut simulate: bool = true; - + // global time let mut time = Duration::new(0,0); - + // 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..6 { + let new_object = PhysicsObject { + name: i.to_string(), + location: [0.0, 0.0, 0.0], + velocity: [rng.gen::() * 10.0, rng.gen::() * 10.0, rng.gen::() * 10.0], + gravity_enabled: true + }; - // create a test physics object - let mut test_object = PhysicsObject { - location: [0.0, 0.0, 10.0], - velocity: [0.0, 5.0, 0.0], - gravity_enabled: true - }; + objects.push(new_object) + } while simulate { // start timing the loop @@ -37,14 +46,16 @@ fn main() { // update if delta_time.as_millis() as u32 >= UPDATE_INTERVAL { - update(delta_time, &mut test_object); + update(delta_time, &mut objects); // reset the delta time delta_time = Duration::new(0,0); } // DEBUG - println!("Time: {}s | test_object | Location: {:?} | Velocity: {:?}", time.as_millis() as f32 / 1000.0, test_object.location, test_object.velocity); + for object in objects.iter() { + println!("Time: {}s | {} | Location: {:?} | Velocity: {:?}", time.as_millis() as f32 / 1000.0, object.name, object.location, object.velocity); + } //display(delta_time, &test_object); @@ -57,7 +68,7 @@ fn main() { // 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, object: &mut PhysicsObject) { +fn update(delta_time: Duration, objects: &mut Vec) { if DEBUG_LOOP { println!("Updating"); } @@ -65,20 +76,26 @@ fn update(delta_time: Duration, object: &mut PhysicsObject) { // calculate the exact timestep (fractional time in seconds) from delta time let timestep: f32 = delta_time.as_millis() as f32 / 1000.0; - // update location based on velocity - for i in 0..3 { - object.location[i] += timestep * object.velocity[i]; - } - - // gravity - if object.gravity_enabled { - object.velocity[2] += GRAVITY * timestep; - } - - // 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); + for object in objects.iter_mut() { + // update location based on velocity + 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]); + } + + // 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); + } } } @@ -92,14 +109,6 @@ fn display(delta_time: Duration, object: &PhysicsObject) { println!("Displaying | Delta Time: {}ms | Relative Time: {}", delta_time.as_millis(), interpolation); } - // create a "render object", which we can apply interpolation to - let mut render_object = *object; - - // interpolate physics values for smooth rendering - for i in 0..3 { - render_object.location[i] += render_object.velocity[i] * interpolation; - } - // DEBUG // println!("test_object | Location: {:?} | Velocity: {:?}", render_object.location, render_object.velocity); }