plumb time ratio everywhere and make a special spot for it in internal instructions

This commit is contained in:
Quaternions 2024-09-16 15:05:11 -07:00
parent a64b81f05e
commit a5efbe6574

View File

@ -22,8 +22,8 @@ use strafesnet_common::physics::Instruction as PhysicsInputInstruction;
//when the physics asks itself what happens next, this is how it's represented //when the physics asks itself what happens next, this is how it's represented
#[derive(Debug)] #[derive(Debug)]
enum PhysicsInternalInstruction{ enum PhysicsInternalInstruction{
CollisionStart(Collision), CollisionStart(Collision,model_physics::GigaTime),
CollisionEnd(Collision), CollisionEnd(Collision,model_physics::GigaTime),
StrafeTick, StrafeTick,
ReachWalkTargetVelocity, ReachWalkTargetVelocity,
// Water, // Water,
@ -793,9 +793,10 @@ impl TouchingState{
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh()); 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,collector.time(),contact.face_id).map(|(_face,time)|{
TimedInstruction{ TimedInstruction{
time, time:relative_body.time+time.into(),
instruction:PhysicsInternalInstruction::CollisionEnd( instruction:PhysicsInternalInstruction::CollisionEnd(
Collision::Contact(*contact) Collision::Contact(*contact),
time
), ),
} }
})); }));
@ -806,9 +807,10 @@ impl TouchingState{
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh()); 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,collector.time()).map(|(_face,time)|{
TimedInstruction{ TimedInstruction{
time, time:relative_body.time+time.into(),
instruction:PhysicsInternalInstruction::CollisionEnd( instruction:PhysicsInternalInstruction::CollisionEnd(
Collision::Intersect(*intersect) Collision::Intersect(*intersect),
time
), ),
} }
})); }));
@ -836,6 +838,11 @@ impl Body{
let dt=time-self.time; let dt=time-self.time;
self.velocity+(self.acceleration*dt).map(|elem|elem.divide().fix_1()) self.velocity+(self.acceleration*dt).map(|elem|elem.divide().fix_1())
} }
pub fn advance_time(&mut self,time:Time){
self.position=self.extrapolated_position(time);
self.velocity=self.extrapolated_velocity(time);
self.time=time;
}
pub fn extrapolated_position_ratio_dt<Num,Den,N1,D1,N2,N3,D2,N4,N5,N6,T1>(&self,dt:integer::Ratio<Num,Den>)->Planar64Vec3 pub fn extrapolated_position_ratio_dt<Num,Den,N1,D1,N2,N3,D2,N4,N5,N6,T1>(&self,dt:integer::Ratio<Num,Den>)->Planar64Vec3
where where
// Why? // Why?
@ -875,10 +882,10 @@ impl Body{
(self.acceleration.map(|elem|dt*elem)+self.velocity) (self.acceleration.map(|elem|dt*elem)+self.velocity)
.map(|elem|elem.divide().fix()) .map(|elem|elem.divide().fix())
} }
pub fn advance_time(&mut self,time:Time){ pub fn advance_time_ratio_dt(&mut self,dt:model_physics::GigaTime){
self.position=self.extrapolated_position(time); self.position=self.extrapolated_position_ratio_dt(dt);
self.velocity=self.extrapolated_velocity(time); self.velocity=self.extrapolated_velocity_ratio_dt(dt);
self.time=time; self.time+=dt.into();
} }
pub fn infinity_dir(&self)->Option<Planar64Vec3>{ pub fn infinity_dir(&self)->Option<Planar64Vec3>{
if self.velocity==vec3::ZERO{ if self.velocity==vec3::ZERO{
@ -1274,12 +1281,15 @@ impl PhysicsContext{
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,data.hitbox_mesh.transformed_mesh()); 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,collector.time())
//temp (?) code to avoid collision loops //temp (?) code to avoid collision loops
.map_or(None,|(face,time)|if time<=state.time{None}else{Some((face,time))}) .map_or(None,|(face,dt)|{
.map(|(face,time)| let time=relative_body.time+dt.into();
if time<=state.time{None}else{Some((time,face,dt))}})
.map(|(time,face,dt)|
TimedInstruction{ TimedInstruction{
time, time,
instruction:PhysicsInternalInstruction::CollisionStart( instruction:PhysicsInternalInstruction::CollisionStart(
Collision::new(convex_mesh_id,face) Collision::new(convex_mesh_id,face),
dt
) )
} }
) )
@ -1719,17 +1729,20 @@ fn collision_end_intersect(
} }
fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<PhysicsInternalInstruction>){ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedInstruction<PhysicsInternalInstruction>){
state.time=ins.time; state.time=ins.time;
let should_advance_body=match ins.instruction{ let (should_advance_body,goober_time)=match ins.instruction{
PhysicsInternalInstruction::CollisionStart(_) PhysicsInternalInstruction::CollisionStart(_,dt)
|PhysicsInternalInstruction::CollisionEnd(_) |PhysicsInternalInstruction::CollisionEnd(_,dt)=>(true,Some(dt)),
|PhysicsInternalInstruction::StrafeTick PhysicsInternalInstruction::StrafeTick
|PhysicsInternalInstruction::ReachWalkTargetVelocity=>true, |PhysicsInternalInstruction::ReachWalkTargetVelocity=>(true,None),
}; };
if should_advance_body{ if should_advance_body{
state.body.advance_time(state.time); match goober_time{
Some(dt)=>state.body.advance_time_ratio_dt(dt),
None=>state.body.advance_time(state.time),
}
} }
match ins.instruction{ match ins.instruction{
PhysicsInternalInstruction::CollisionStart(collision)=>{ PhysicsInternalInstruction::CollisionStart(collision,_)=>{
let mode=data.modes.get_mode(state.mode_state.get_mode_id()); let mode=data.modes.get_mode(state.mode_state.get_mode_id());
match collision{ match collision{
Collision::Contact(contact)=>collision_start_contact( Collision::Contact(contact)=>collision_start_contact(
@ -1750,7 +1763,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim
), ),
} }
}, },
PhysicsInternalInstruction::CollisionEnd(collision)=>match collision{ PhysicsInternalInstruction::CollisionEnd(collision,_)=>match collision{
Collision::Contact(contact)=>collision_end_contact( Collision::Contact(contact)=>collision_end_contact(
&mut state.move_state,&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state, &mut state.move_state,&mut state.body,&mut state.touching,&data.models,&data.hitbox_mesh,&state.style,&state.camera,&state.input_state,
data.models.contact_attr(contact.model_id), data.models.contact_attr(contact.model_id),
@ -1967,7 +1980,7 @@ mod test{
let platform_mesh=h0.transformed_mesh(); let platform_mesh=h0.transformed_mesh();
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(platform_mesh,hitbox_mesh); let minkowski=model_physics::MinkowskiMesh::minkowski_sum(platform_mesh,hitbox_mesh);
let collision=minkowski.predict_collision_in(&relative_body,Time::MAX); let collision=minkowski.predict_collision_in(&relative_body,Time::MAX);
assert_eq!(collision.map(|tup|tup.1),expected_collision_time,"Incorrect time of collision"); assert_eq!(collision.map(|tup|tup.1.into()),expected_collision_time,"Incorrect time of collision");
} }
fn test_collision_rotated(relative_body:Body,expected_collision_time:Option<Time>){ fn test_collision_rotated(relative_body:Body,expected_collision_time:Option<Time>){
let h0=HitboxMesh::new(PhysicsMesh::unit_cube(), let h0=HitboxMesh::new(PhysicsMesh::unit_cube(),
@ -1985,7 +1998,7 @@ mod test{
let platform_mesh=h0.transformed_mesh(); let platform_mesh=h0.transformed_mesh();
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(platform_mesh,hitbox_mesh); let minkowski=model_physics::MinkowskiMesh::minkowski_sum(platform_mesh,hitbox_mesh);
let collision=minkowski.predict_collision_in(&relative_body,Time::MAX); let collision=minkowski.predict_collision_in(&relative_body,Time::MAX);
assert_eq!(collision.map(|tup|tup.1),expected_collision_time,"Incorrect time of collision"); assert_eq!(collision.map(|tup|tup.1.into()),expected_collision_time,"Incorrect time of collision");
} }
fn test_collision(relative_body:Body,expected_collision_time:Option<Time>){ fn test_collision(relative_body:Body,expected_collision_time:Option<Time>){
test_collision_axis_aligned(relative_body.clone(),expected_collision_time); test_collision_axis_aligned(relative_body.clone(),expected_collision_time);