completely rewrote delta time, changed PhysicsObjects to Particles

This commit is contained in:
skyeshroom 2021-08-10 11:44:59 -07:00
parent 472b736c9c
commit e3818ea2c9
3 changed files with 82 additions and 251 deletions

172
Cargo.lock generated
View File

@ -2,112 +2,12 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 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]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.3" version = "0.2.3"
@ -123,7 +23,6 @@ dependencies = [
name = "hypoloop" name = "hypoloop"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"futures",
"rand", "rand",
] ]
@ -133,60 +32,12 @@ version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" 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]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.10" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 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]] [[package]]
name = "rand" name = "rand"
version = "0.8.4" version = "0.8.4"
@ -227,29 +78,6 @@ dependencies = [
"rand_core", "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]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.2+wasi-snapshot-preview1" version = "0.10.2+wasi-snapshot-preview1"

View File

@ -6,5 +6,4 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
futures = "0.3.16"
rand = "0.8.4" rand = "0.8.4"

View File

@ -1,3 +1,4 @@
use core::time;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use rand::Rng; use rand::Rng;
@ -6,129 +7,113 @@ const UPDATE_INTERVAL: u32 = 40;
// debug constants // debug constants
const DEBUG_LOOP: bool = false; const DEBUG_LOOP: bool = false;
const DEBUG_OBJECTS: bool = false; const DEBUG_TIME: bool = false;
const DEBUG_PERFORMANCE: bool = true; const DEBUG_PARTICLES: bool = true;
const FAIL_DELAY: u32 = 50;
// scene constants // scene constants
const TIMESCALE: f32 = 1.0;
const GRAVITY: f32 = -9.8; 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)] #[derive(Copy, Clone)]
struct PhysicsObject { struct Particle {
location: [f32; 3], location: [f32; 3],
velocity: [f32; 3], velocity: [f32; 3],
acceleration: [f32; 3],
gravity_enabled: bool gravity_enabled: bool
} }
fn main() { fn main() {
let mut simulate: bool = true; let mut simulate: bool = true;
// global time // start the clock to keep track of real time
let mut time = Duration::new(0,0); let clock_start = Instant::now();
// track the delta time (the duration of the previous loop in milliseconds) // track the end time of the last loop
let mut delta_time = Duration::new(0, 0); let mut end_time = Instant::now();
// a vector of objects to calculate physics for // keep track of the last tick time
let mut objects: Vec<PhysicsObject> = vec![]; let mut last_tick = Instant::now();
let mut rng = rand::thread_rng();
for i in 0..OBJECT_COUNT { // a vector of particles
let new_object = PhysicsObject { let mut particles: Vec<Particle> = vec![];
location: [0.0, 0.0, 0.0], for i in 0..PARTICLE_COUNT {
velocity: [rng.gen::<f32>() * 10.0, rng.gen::<f32>() * 10.0, rng.gen::<f32>() * 10.0], let new_particle = Particle {
location: [0.0, 0.0, 10.0],
velocity: [0.0; 3],
acceleration: [0.0; 3],
gravity_enabled: true gravity_enabled: true
}; };
objects.push(new_object) particles.push(new_particle)
} }
while simulate { while simulate {
// start timing the loop
let start_time = Instant::now();
// update // update
if delta_time.as_millis() as u32 >= UPDATE_INTERVAL { if delta_time(last_tick) >= UPDATE_INTERVAL {
update(delta_time, &mut objects);
// DEBUG // DEBUG
if DEBUG_PERFORMANCE { if DEBUG_TIME {
let interval = delta_time.as_millis() as u32; println!("Real time: {}ms | Delta time: {}ms", delta_time(clock_start), delta_time(last_tick));
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::<f32>() * 10.0, rng.gen::<f32>() * 10.0, rng.gen::<f32>() * 10.0],
gravity_enabled: true
};
objects.push(new_object)
} }
} else { if DEBUG_PARTICLES {
// stop the simulation for i in 0..particles.len() {
simulate = false; 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 update(delta_time(last_tick), &mut particles);
delta_time = Duration::new(0,0);
// record last tick time
last_tick = Instant::now();
} }
//display(delta_time, &test_object); //display(delta_time, &test_particle);
// 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 function // 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 // 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<PhysicsObject>) { fn update(delta_time: u32, particles: &mut Vec<Particle>) {
if DEBUG_LOOP { if DEBUG_LOOP {
println!("Updating"); println!("Updating");
} }
// calculate the exact timestep (fractional time in seconds) from delta time // 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() { for particle in particles.iter_mut() {
// update location based on velocity // 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 { for i in 0..3 {
// location += timestep * velocity // location += timestep * velocity
// use an FMA here to halve the rounding error particle.location[i] = timestep.mul_add(particle.velocity[i], particle.location[i]);
object.location[i] = timestep.mul_add(object.velocity[i], object.location[i]);
} }
// gravity // prevent the particle from going below the ground plane, and kill downward velocity upon "hitting" the ground plane
if object.gravity_enabled { if particle.location[2] <= 0.0 {
// velocity += timestep * gravity particle.location[2] = 0.0;
// use an FMA here to halve the rounding error particle.velocity[2] = particle.velocity[2].max(0.0);
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);
} }
} }
} }
// render function // render function
fn display(delta_time: Duration, object: &PhysicsObject) { fn display(delta_time: Duration, particle: &Particle) {
// calculate interpolation via delta time // calculate interpolation via delta time
let interpolation: f32 = delta_time.as_millis() as f32 / UPDATE_INTERVAL as f32; 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 // 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 // 1D linear interpolation
fn lerp_1d(x: f64, y: f64, a: f64) -> f64 { fn lerp_1d(x: f64, y: f64, a: f64) -> f64 {
x + ((y - x) * a) 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::<f32>();
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
}