From 77aa83d6acfa24f33af0f43ae866a7fbc1953234 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Mon, 20 Jan 2025 07:51:39 -0800 Subject: [PATCH] physics: explicit start_time --- strafe-client/src/model_physics.rs | 31 +++++++++++++++--------------- strafe-client/src/physics.rs | 15 ++++++++------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/strafe-client/src/model_physics.rs b/strafe-client/src/model_physics.rs index 1adfd41..57f9ec3 100644 --- a/strafe-client/src/model_physics.rs +++ b/strafe-client/src/model_physics.rs @@ -718,7 +718,7 @@ impl MinkowskiMesh<'_>{ // // Most of the calculation time is just calculating the starting point // for the "actual" crawling algorithm below (predict_collision_{in|out}). - fn closest_fev_not_inside(&self,mut infinity_body:Body)->Option>{ + fn closest_fev_not_inside(&self,mut infinity_body:Body,start_time:Time,)->Option>{ infinity_body.infinity_dir().map_or(None,|dir|{ let infinity_fev=self.infinity_fev(-dir,infinity_body.position); //a line is simpler to solve than a parabola @@ -726,40 +726,39 @@ impl MinkowskiMesh<'_>{ infinity_body.acceleration=vec3::ZERO; //crawl in from negative infinity along a tangent line to get the closest fev // TODO: change crawl_fev args to delta time? Optional values? - match infinity_fev.crawl(self,&infinity_body,Time::MIN/4,infinity_body.time){ + match infinity_fev.crawl(self,&infinity_body,Time::MIN/4,start_time){ crate::face_crawler::CrawlResult::Miss(fev)=>Some(fev), crate::face_crawler::CrawlResult::Hit(_,_)=>None, } }) } - pub fn predict_collision_in(&self,relative_body:&Body,time_limit:Time)->Option<(MinkowskiFace,GigaTime)>{ - self.closest_fev_not_inside(relative_body.clone()).map_or(None,|fev|{ + pub fn predict_collision_in(&self,relative_body:&Body,start_time:Time,time_limit:Time)->Option<(MinkowskiFace,GigaTime)>{ + self.closest_fev_not_inside(relative_body.clone(),start_time).map_or(None,|fev|{ //continue forwards along the body parabola - match fev.crawl(self,relative_body,relative_body.time,time_limit){ + match fev.crawl(self,relative_body,start_time,time_limit){ crate::face_crawler::CrawlResult::Miss(_)=>None, crate::face_crawler::CrawlResult::Hit(face,time)=>Some((face,time)), } }) } - pub fn predict_collision_out(&self,relative_body:&Body,time_limit:Time)->Option<(MinkowskiFace,GigaTime)>{ + pub fn predict_collision_out(&self,relative_body:&Body,start_time:Time,time_limit:Time)->Option<(MinkowskiFace,GigaTime)>{ //create an extrapolated body at time_limit - let infinity_body=Body::new( - relative_body.extrapolated_position(time_limit), - -relative_body.extrapolated_velocity(time_limit), - relative_body.acceleration, - -time_limit, - ); - self.closest_fev_not_inside(infinity_body).map_or(None,|fev|{ + let infinity_body=-relative_body.clone(); + self.closest_fev_not_inside(infinity_body,-time_limit).map_or(None,|fev|{ //continue backwards along the body parabola - match fev.crawl(self,&-relative_body.clone(),-time_limit,-relative_body.time){ + match fev.crawl(self,&infinity_body,-time_limit,-start_time){ crate::face_crawler::CrawlResult::Miss(_)=>None, crate::face_crawler::CrawlResult::Hit(face,time)=>Some((face,-time)),//no need to test -timeOption<(MinkowskiEdge,GigaTime)>{ + pub fn predict_collision_face_out(&self,relative_body:&Body,start_time:Time,time_limit:Time,contact_face_id:MinkowskiFace)->Option<(MinkowskiEdge,GigaTime)>{ //no algorithm needed, there is only one state and two cases (Edge,None) //determine when it passes an edge ("sliding off" case) + let start_time={ + let r=(start_time-relative_body.time).to_ratio(); + Ratio::new(r.num,r.den) + }; let mut best_time={ let r=(time_limit-relative_body.time).to_ratio(); Ratio::new(r.num.fix_4(),r.den.fix_4()) @@ -775,7 +774,7 @@ impl MinkowskiMesh<'_>{ //WARNING! d outside of *2 //WARNING: truncated precision for dt in Fixed::<4,128>::zeroes2(((n.dot(relative_body.position))*2-d).fix_4(),n.dot(relative_body.velocity).fix_4()*2,n.dot(relative_body.acceleration).fix_4()){ - if Ratio::new(Planar64::ZERO,Planar64::EPSILON).le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(relative_body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ + if start_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(relative_body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ best_time=dt; best_edge=Some(directed_edge_id); break; diff --git a/strafe-client/src/physics.rs b/strafe-client/src/physics.rs index 29758ed..b038876 100644 --- a/strafe-client/src/physics.rs +++ b/strafe-client/src/physics.rs @@ -776,13 +776,14 @@ impl TouchingState{ }).collect(); *acceleration=crate::push_solve::push_solve(&contacts,*acceleration); } - fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,time:Time){ - let relative_body=crate::body::VirtualBody::relative(&Body::ZERO,body).body(time); + fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,start_time:Time){ + // let relative_body=crate::body::VirtualBody::relative(&Body::ZERO,body).body(time); + let relative_body=body; for contact in &self.contacts{ //detect face slide off let model_mesh=models.contact_mesh(contact); let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh()); - collector.collect(minkowski.predict_collision_face_out(&relative_body,collector.time(),contact.face_id).map(|(_face,time)|{ + collector.collect(minkowski.predict_collision_face_out(&relative_body,start_time,collector.time(),contact.face_id).map(|(_face,time)|{ TimedInstruction{ time:relative_body.time+time.into(), instruction:InternalInstruction::CollisionEnd( @@ -796,7 +797,7 @@ impl TouchingState{ //detect model collision in reverse let model_mesh=models.intersect_mesh(intersect); let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh()); - collector.collect(minkowski.predict_collision_out(&relative_body,collector.time()).map(|(_face,time)|{ + collector.collect(minkowski.predict_collision_out(&relative_body,start_time,collector.time()).map(|(_face,time)|{ TimedInstruction{ time:relative_body.time+time.into(), instruction:InternalInstruction::CollisionEnd( @@ -1128,7 +1129,7 @@ impl PhysicsData{ //no checks are needed because of the time limits. let model_mesh=data.models.mesh(convex_mesh_id); let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,data.hitbox_mesh.transformed_mesh()); - collector.collect(minkowski.predict_collision_in(relative_body,collector.time()) + collector.collect(minkowski.predict_collision_in(relative_body,state.time,collector.time()) //temp (?) code to avoid collision loops .map_or(None,|(face,dt)|{ // this must be rounded to avoid the infinite loop when hitting the start zone @@ -1868,7 +1869,7 @@ mod test{ let hitbox_mesh=h1.transformed_mesh(); let platform_mesh=h0.transformed_mesh(); let minkowski=model_physics::MinkowskiMesh::minkowski_sum(platform_mesh,hitbox_mesh); - let collision=minkowski.predict_collision_in(&relative_body,Time::from_secs(10)); + let collision=minkowski.predict_collision_in(&relative_body,Time::ZERO,Time::from_secs(10)); assert_eq!(collision.map(|tup|relative_body.time+tup.1.into()),expected_collision_time,"Incorrect time of collision"); } fn test_collision_rotated(relative_body:Body,expected_collision_time:Option