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
#[derive(Debug)]
enum PhysicsInternalInstruction{
CollisionStart(Collision),
CollisionEnd(Collision),
CollisionStart(Collision,model_physics::GigaTime),
CollisionEnd(Collision,model_physics::GigaTime),
StrafeTick,
ReachWalkTargetVelocity,
// Water,
@ -793,9 +793,10 @@ impl TouchingState{
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)|{
TimedInstruction{
time,
time:relative_body.time+time.into(),
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());
collector.collect(minkowski.predict_collision_out(&relative_body,collector.time()).map(|(_face,time)|{
TimedInstruction{
time,
time:relative_body.time+time.into(),
instruction:PhysicsInternalInstruction::CollisionEnd(
Collision::Intersect(*intersect)
Collision::Intersect(*intersect),
time
),
}
}));
@ -836,6 +838,11 @@ impl Body{
let dt=time-self.time;
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
where
// Why?
@ -875,10 +882,10 @@ impl Body{
(self.acceleration.map(|elem|dt*elem)+self.velocity)
.map(|elem|elem.divide().fix())
}
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 advance_time_ratio_dt(&mut self,dt:model_physics::GigaTime){
self.position=self.extrapolated_position_ratio_dt(dt);
self.velocity=self.extrapolated_velocity_ratio_dt(dt);
self.time+=dt.into();
}
pub fn infinity_dir(&self)->Option<Planar64Vec3>{
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());
collector.collect(minkowski.predict_collision_in(relative_body,collector.time())
//temp (?) code to avoid collision loops
.map_or(None,|(face,time)|if time<=state.time{None}else{Some((face,time))})
.map(|(face,time)|
.map_or(None,|(face,dt)|{
let time=relative_body.time+dt.into();
if time<=state.time{None}else{Some((time,face,dt))}})
.map(|(time,face,dt)|
TimedInstruction{
time,
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>){
state.time=ins.time;
let should_advance_body=match ins.instruction{
PhysicsInternalInstruction::CollisionStart(_)
|PhysicsInternalInstruction::CollisionEnd(_)
|PhysicsInternalInstruction::StrafeTick
|PhysicsInternalInstruction::ReachWalkTargetVelocity=>true,
let (should_advance_body,goober_time)=match ins.instruction{
PhysicsInternalInstruction::CollisionStart(_,dt)
|PhysicsInternalInstruction::CollisionEnd(_,dt)=>(true,Some(dt)),
PhysicsInternalInstruction::StrafeTick
|PhysicsInternalInstruction::ReachWalkTargetVelocity=>(true,None),
};
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{
PhysicsInternalInstruction::CollisionStart(collision)=>{
PhysicsInternalInstruction::CollisionStart(collision,_)=>{
let mode=data.modes.get_mode(state.mode_state.get_mode_id());
match collision{
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(
&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),
@ -1967,7 +1980,7 @@ mod test{
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::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>){
let h0=HitboxMesh::new(PhysicsMesh::unit_cube(),
@ -1985,7 +1998,7 @@ mod test{
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::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>){
test_collision_axis_aligned(relative_body.clone(),expected_collision_time);