From ad7abbdf1ccd8c9916fdbbc4f1cc85788ba3f22f Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 18 Sep 2023 18:06:03 -0700 Subject: [PATCH] rework predict_collision_end --- src/body.rs | 305 ++++++++++++++++++++++++--------------------- src/instruction.rs | 2 +- 2 files changed, 166 insertions(+), 141 deletions(-) diff --git a/src/body.rs b/src/body.rs index 00fa85fb..964eeba7 100644 --- a/src/body.rs +++ b/src/body.rs @@ -20,8 +20,6 @@ pub struct Body { velocity: glam::Vec3,//I64 where 2^32 = 1 u/s acceleration: glam::Vec3,//I64 where 2^32 = 1 u/s/s time: TIME,//nanoseconds x xxxxD! - //origin_time = timestamp of position and velocity - //processed_time = starting time for new events. prevents colliding with the analytic euqation in the past } pub enum MoveRestriction { @@ -260,7 +258,7 @@ impl Model { //need non-face (full model) variant for CanCollide false objects //OR have a separate list from contacts for model intersection -#[derive(Eq, Hash, PartialEq)] +#[derive(Clone,Eq,Hash,PartialEq)] pub struct RelativeCollision { face: TreyMeshFace,//just an id model: u32,//using id to avoid lifetimes @@ -303,9 +301,9 @@ impl Body { impl PhysicsState { //tickless gaming - pub fn run(&mut self, time: TIME){ + pub fn run(&mut self, time_limit:TIME){ //prepare is ommitted - everything is done via instructions. - while let Some(instruction) = self.next_instruction(time) {//collect + while let Some(instruction) = self.next_instruction(time_limit) {//collect //advance //self.advance_time(instruction.time); //process @@ -369,229 +367,256 @@ impl PhysicsState { } aabb } - fn predict_collision_end(&self,model:&Model,time_limit:TIME,model_id:u32) -> Option> { + fn predict_collision_end(&self,time:TIME,time_limit:TIME,collision_data:&RelativeCollision) -> Option> { //must treat cancollide false objects differently: you may not exit through the same face you entered. //RelativeCollsion must reference the full model instead of a particular face //this is Ctrl+C Ctrl+V of predict_collision_start but with v=-v before the calc and t=-t after the calc //find best t - let mut best_delta_time=time_limit-self.body.time; - let mut best_face:Option=None; + let mut best_time=time_limit; + let mut exit_face:Option=None; let mesh0=self.mesh(); - let mesh1=model.mesh(); - let (p,v,a)=(self.body.position,-self.body.velocity,self.body.acceleration); + let mesh1=self.models_cringe_clone.get(collision_data.model as usize).unwrap().mesh(); + let (v,a)=(-self.body.velocity,self.body.acceleration); //collect x - for t in zeroes2(mesh0.max.x-mesh1.min.x, v.x, a.x) { - //negative t = back in time - //must be moving towards surface to collide - //must beat the current soonest collision time - //must be moving towards surface - let t_time=((-t as f64)*1_000_000_000f64) as TIME; - if 0<=t_time&&t_time{ + for t in zeroes2(mesh0.max.x-mesh1.min.x,v.x,a.x) { + //negative t = back in time + //must be moving towards surface to collide + //must beat the current soonest collision time + //must be moving towards surface + let t_time=self.body.time+((-t as f64)*1_000_000_000f64) as TIME; + if time<=t_time&&t_time{ + //generate event if v.x<0||a.x<0 + if -v.x<0f32{ + best_time=time; + exit_face=Some(TreyMeshFace::Left); + } + }, + AabbFace::Right=>{ + //generate event if 0{ + for t in zeroes2(mesh0.max.y-mesh1.min.y,v.y,a.y) { + //negative t = back in time + //must be moving towards surface to collide + //must beat the current soonest collision time + //must be moving towards surface + let t_time=self.body.time+((-t as f64)*1_000_000_000f64) as TIME; + if time<=t_time&&t_time{ + //generate event if v.y<0||a.y<0 + if -v.y<0f32{ + best_time=time; + exit_face=Some(TreyMeshFace::Bottom); + } + }, + AabbFace::Top=>{ + //generate event if 0{ + for t in zeroes2(mesh0.max.z-mesh1.min.z,v.z,a.z) { + //negative t = back in time + //must be moving towards surface to collide + //must beat the current soonest collision time + //must be moving towards surface + let t_time=self.body.time+((-t as f64)*1_000_000_000f64) as TIME; + if time<=t_time&&t_time{ + //generate event if v.z<0||a.z<0 + if -v.z<0f32{ + best_time=time; + exit_face=Some(TreyMeshFace::Front); + } + }, + AabbFace::Back=>{ + //generate event if 0 Option> { + fn predict_collision_start(&self,time:TIME,time_limit:TIME,model_id:u32) -> Option> { //find best t - let mut best_delta_time=time_limit-self.body.time; + let mut best_time=time_limit; let mut best_face:Option=None; let mesh0=self.mesh(); - let mesh1=model.mesh(); + let mesh1=self.models_cringe_clone.get(model_id as usize).unwrap().mesh(); let (p,v,a)=(self.body.position,self.body.velocity,self.body.acceleration); //collect x - for t in zeroes2(mesh0.max.x-mesh1.min.x, v.x, a.x) { + for t in zeroes2(mesh0.max.x-mesh1.min.x,v.x,a.x) { //negative t = back in time //must be moving towards surface to collide //must beat the current soonest collision time //must be moving towards surface - let t_time=((t as f64)*1_000_000_000f64) as TIME; - if 0<=t_time&&t_time for PhysicsState } //check for collision stop instructions with curent contacts for collision_data in self.contacts.iter() { - collector.collect(self.predict_collision_end(self.models_cringe_clone.get(collision_data.model as usize).unwrap(),time_limit,collision_data.model)); + collector.collect(self.predict_collision_end(self.time,time_limit,collision_data)); } //check for collision start instructions (against every part in the game with no optimization!!) - for (i,model) in self.models_cringe_clone.iter().enumerate() { - collector.collect(self.predict_collision_start(model,time_limit,i as u32)); + for i in 0..self.models_cringe_clone.len() { + collector.collect(self.predict_collision_start(self.time,time_limit,i as u32)); } if self.grounded { //walk maintenance diff --git a/src/instruction.rs b/src/instruction.rs index a56b848f..9ac38699 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -4,7 +4,7 @@ pub struct TimedInstruction { } pub trait InstructionEmitter { - fn next_instruction(&self, time:crate::body::TIME) -> Option>; + fn next_instruction(&self, time_limit:crate::body::TIME) -> Option>; } pub trait InstructionConsumer { fn process_instruction(&mut self, instruction:TimedInstruction);