forked from StrafesNET/strafe-project
physics: explicit start_time
This commit is contained in:
parent
184b12a9cc
commit
77aa83d6ac
@ -718,7 +718,7 @@ impl MinkowskiMesh<'_>{
|
|||||||
//
|
//
|
||||||
// Most of the calculation time is just calculating the starting point
|
// Most of the calculation time is just calculating the starting point
|
||||||
// for the "actual" crawling algorithm below (predict_collision_{in|out}).
|
// for the "actual" crawling algorithm below (predict_collision_{in|out}).
|
||||||
fn closest_fev_not_inside(&self,mut infinity_body:Body)->Option<FEV<MinkowskiMesh>>{
|
fn closest_fev_not_inside(&self,mut infinity_body:Body,start_time:Time,)->Option<FEV<MinkowskiMesh>>{
|
||||||
infinity_body.infinity_dir().map_or(None,|dir|{
|
infinity_body.infinity_dir().map_or(None,|dir|{
|
||||||
let infinity_fev=self.infinity_fev(-dir,infinity_body.position);
|
let infinity_fev=self.infinity_fev(-dir,infinity_body.position);
|
||||||
//a line is simpler to solve than a parabola
|
//a line is simpler to solve than a parabola
|
||||||
@ -726,40 +726,39 @@ impl MinkowskiMesh<'_>{
|
|||||||
infinity_body.acceleration=vec3::ZERO;
|
infinity_body.acceleration=vec3::ZERO;
|
||||||
//crawl in from negative infinity along a tangent line to get the closest fev
|
//crawl in from negative infinity along a tangent line to get the closest fev
|
||||||
// TODO: change crawl_fev args to delta time? Optional values?
|
// 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::Miss(fev)=>Some(fev),
|
||||||
crate::face_crawler::CrawlResult::Hit(_,_)=>None,
|
crate::face_crawler::CrawlResult::Hit(_,_)=>None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn predict_collision_in(&self,relative_body:&Body,time_limit:Time)->Option<(MinkowskiFace,GigaTime)>{
|
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()).map_or(None,|fev|{
|
self.closest_fev_not_inside(relative_body.clone(),start_time).map_or(None,|fev|{
|
||||||
//continue forwards along the body parabola
|
//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::Miss(_)=>None,
|
||||||
crate::face_crawler::CrawlResult::Hit(face,time)=>Some((face,time)),
|
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
|
//create an extrapolated body at time_limit
|
||||||
let infinity_body=Body::new(
|
let infinity_body=-relative_body.clone();
|
||||||
relative_body.extrapolated_position(time_limit),
|
self.closest_fev_not_inside(infinity_body,-time_limit).map_or(None,|fev|{
|
||||||
-relative_body.extrapolated_velocity(time_limit),
|
|
||||||
relative_body.acceleration,
|
|
||||||
-time_limit,
|
|
||||||
);
|
|
||||||
self.closest_fev_not_inside(infinity_body).map_or(None,|fev|{
|
|
||||||
//continue backwards along the body parabola
|
//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::Miss(_)=>None,
|
||||||
crate::face_crawler::CrawlResult::Hit(face,time)=>Some((face,-time)),//no need to test -time<time_limit because of the first step
|
crate::face_crawler::CrawlResult::Hit(face,time)=>Some((face,-time)),//no need to test -time<time_limit because of the first step
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn predict_collision_face_out(&self,relative_body:&Body,time_limit:Time,contact_face_id:MinkowskiFace)->Option<(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)
|
//no algorithm needed, there is only one state and two cases (Edge,None)
|
||||||
//determine when it passes an edge ("sliding off" case)
|
//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 mut best_time={
|
||||||
let r=(time_limit-relative_body.time).to_ratio();
|
let r=(time_limit-relative_body.time).to_ratio();
|
||||||
Ratio::new(r.num.fix_4(),r.den.fix_4())
|
Ratio::new(r.num.fix_4(),r.den.fix_4())
|
||||||
@ -775,7 +774,7 @@ impl MinkowskiMesh<'_>{
|
|||||||
//WARNING! d outside of *2
|
//WARNING! d outside of *2
|
||||||
//WARNING: truncated precision
|
//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()){
|
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_time=dt;
|
||||||
best_edge=Some(directed_edge_id);
|
best_edge=Some(directed_edge_id);
|
||||||
break;
|
break;
|
||||||
|
@ -776,13 +776,14 @@ impl TouchingState{
|
|||||||
}).collect();
|
}).collect();
|
||||||
*acceleration=crate::push_solve::push_solve(&contacts,*acceleration);
|
*acceleration=crate::push_solve::push_solve(&contacts,*acceleration);
|
||||||
}
|
}
|
||||||
fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector<InternalInstruction,TimeInner>,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,time:Time){
|
fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector<InternalInstruction,TimeInner>,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=crate::body::VirtualBody::relative(&Body::ZERO,body).body(time);
|
||||||
|
let relative_body=body;
|
||||||
for contact in &self.contacts{
|
for contact in &self.contacts{
|
||||||
//detect face slide off
|
//detect face slide off
|
||||||
let model_mesh=models.contact_mesh(contact);
|
let model_mesh=models.contact_mesh(contact);
|
||||||
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,start_time,collector.time(),contact.face_id).map(|(_face,time)|{
|
||||||
TimedInstruction{
|
TimedInstruction{
|
||||||
time:relative_body.time+time.into(),
|
time:relative_body.time+time.into(),
|
||||||
instruction:InternalInstruction::CollisionEnd(
|
instruction:InternalInstruction::CollisionEnd(
|
||||||
@ -796,7 +797,7 @@ impl TouchingState{
|
|||||||
//detect model collision in reverse
|
//detect model collision in reverse
|
||||||
let model_mesh=models.intersect_mesh(intersect);
|
let model_mesh=models.intersect_mesh(intersect);
|
||||||
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,start_time,collector.time()).map(|(_face,time)|{
|
||||||
TimedInstruction{
|
TimedInstruction{
|
||||||
time:relative_body.time+time.into(),
|
time:relative_body.time+time.into(),
|
||||||
instruction:InternalInstruction::CollisionEnd(
|
instruction:InternalInstruction::CollisionEnd(
|
||||||
@ -1128,7 +1129,7 @@ impl PhysicsData{
|
|||||||
//no checks are needed because of the time limits.
|
//no checks are needed because of the time limits.
|
||||||
let model_mesh=data.models.mesh(convex_mesh_id);
|
let model_mesh=data.models.mesh(convex_mesh_id);
|
||||||
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,state.time,collector.time())
|
||||||
//temp (?) code to avoid collision loops
|
//temp (?) code to avoid collision loops
|
||||||
.map_or(None,|(face,dt)|{
|
.map_or(None,|(face,dt)|{
|
||||||
// this must be rounded to avoid the infinite loop when hitting the start zone
|
// 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 hitbox_mesh=h1.transformed_mesh();
|
||||||
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::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");
|
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<Time>){
|
fn test_collision_rotated(relative_body:Body,expected_collision_time:Option<Time>){
|
||||||
@ -1886,7 +1887,7 @@ mod test{
|
|||||||
let hitbox_mesh=h1.transformed_mesh();
|
let hitbox_mesh=h1.transformed_mesh();
|
||||||
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::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");
|
assert_eq!(collision.map(|tup|relative_body.time+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>){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user