check touching before testing collision
This commit is contained in:
@@ -614,7 +614,7 @@ impl MoveState{
|
||||
// TODO: unduplicate this code
|
||||
match self.get_walk_state(){
|
||||
// did you stop touching the thing you were walking on?
|
||||
Some(walk_state)=>if !touching.contacts.contains(&walk_state.contact){
|
||||
Some(walk_state)=>if !touching.contacts.contains_key(&walk_state.contact.convex_mesh_id){
|
||||
self.set_move_state(MoveState::Air,body,touching,models,hitbox_mesh,style,camera,input_state);
|
||||
}else{
|
||||
// stopped touching something else while walking
|
||||
@@ -753,8 +753,8 @@ impl Collision{
|
||||
}
|
||||
#[derive(Clone,Debug,Default)]
|
||||
struct TouchingState{
|
||||
contacts:HashSet<ContactCollision>,
|
||||
intersects:HashSet<IntersectCollision>,
|
||||
contacts:HashMap<ConvexMeshId<ContactModelId>,model_physics::MinkowskiFace>,
|
||||
intersects:HashSet<ConvexMeshId<IntersectModelId>>,
|
||||
}
|
||||
impl TouchingState{
|
||||
fn clear(&mut self){
|
||||
@@ -763,20 +763,20 @@ impl TouchingState{
|
||||
}
|
||||
fn insert(&mut self,collision:Collision)->bool{
|
||||
match collision{
|
||||
Collision::Contact(collision)=>self.contacts.insert(collision),
|
||||
Collision::Intersect(collision)=>self.intersects.insert(collision),
|
||||
Collision::Contact(collision)=>self.contacts.insert(collision.convex_mesh_id,collision.face_id).is_none(),
|
||||
Collision::Intersect(collision)=>self.intersects.insert(collision.convex_mesh_id),
|
||||
}
|
||||
}
|
||||
fn contains(&self,collision:&Collision)->bool{
|
||||
match collision{
|
||||
Collision::Contact(collision)=>self.contacts.contains(collision),
|
||||
Collision::Intersect(collision)=>self.intersects.contains(collision),
|
||||
fn contains(&self,convex_mesh_id:&ConvexMeshId<PhysicsModelId>)->bool{
|
||||
match convex_mesh_id.model_id{
|
||||
PhysicsModelId::Contact(contact_model_id)=>self.contacts.contains_key(&convex_mesh_id.map(contact_model_id)),
|
||||
PhysicsModelId::Intersect(intersect_model_id)=>self.intersects.contains(&convex_mesh_id.map(intersect_model_id)),
|
||||
}
|
||||
}
|
||||
fn remove(&mut self,collision:&Collision)->bool{
|
||||
match collision{
|
||||
Collision::Contact(collision)=>self.contacts.remove(collision),
|
||||
Collision::Intersect(collision)=>self.intersects.remove(collision),
|
||||
fn remove(&mut self,convex_mesh_id:&ConvexMeshId<PhysicsModelId>)->bool{
|
||||
match convex_mesh_id.model_id{
|
||||
PhysicsModelId::Contact(contact_model_id)=>self.contacts.remove(&convex_mesh_id.map(contact_model_id)).is_some(),
|
||||
PhysicsModelId::Intersect(intersect_model_id)=>self.intersects.remove(&convex_mesh_id.map(intersect_model_id)),
|
||||
}
|
||||
}
|
||||
fn base_acceleration(&self,models:&PhysicsModels,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState)->Planar64Vec3{
|
||||
@@ -785,13 +785,13 @@ impl TouchingState{
|
||||
a+=rocket_settings.acceleration(style.get_propulsion_control_dir(camera,input_state.controls));
|
||||
}
|
||||
//add accelerators
|
||||
for contact in &self.contacts{
|
||||
if let Some(accelerator)=&models.contact_attr(contact.convex_mesh_id.model_id).general.accelerator{
|
||||
for contact in self.contacts.keys(){
|
||||
if let Some(accelerator)=&models.contact_attr(contact.model_id).general.accelerator{
|
||||
a+=accelerator.acceleration;
|
||||
}
|
||||
}
|
||||
for intersect in &self.intersects{
|
||||
if let Some(accelerator)=&models.intersect_attr(intersect.convex_mesh_id.model_id).general.accelerator{
|
||||
if let Some(accelerator)=&models.intersect_attr(intersect.model_id).general.accelerator{
|
||||
a+=accelerator.acceleration;
|
||||
}
|
||||
}
|
||||
@@ -799,8 +799,9 @@ impl TouchingState{
|
||||
a
|
||||
}
|
||||
fn constrain_velocity(&self,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,velocity:Planar64Vec3)->Planar64Vec3{
|
||||
let contacts:Vec<_>=self.contacts.iter().map(|contact|{
|
||||
let n=contact_normal(models,hitbox_mesh,contact);
|
||||
let contacts:Vec<_>=self.contacts.iter().map(|(&convex_mesh_id,&face_id)|{
|
||||
let contact=ContactCollision{face_id,convex_mesh_id};
|
||||
let n=contact_normal(models,hitbox_mesh,&contact);
|
||||
crate::push_solve::Contact{
|
||||
position:vec3::ZERO,
|
||||
velocity:n,
|
||||
@@ -810,8 +811,9 @@ impl TouchingState{
|
||||
crate::push_solve::push_solve(&contacts,velocity)
|
||||
}
|
||||
fn constrain_acceleration(&self,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,acceleration:Planar64Vec3)->Planar64Vec3{
|
||||
let contacts:Vec<_>=self.contacts.iter().map(|contact|{
|
||||
let n=contact_normal(models,hitbox_mesh,contact);
|
||||
let contacts:Vec<_>=self.contacts.iter().map(|(&convex_mesh_id,&face_id)|{
|
||||
let contact=ContactCollision{face_id,convex_mesh_id};
|
||||
let n=contact_normal(models,hitbox_mesh,&contact);
|
||||
crate::push_solve::Contact{
|
||||
position:vec3::ZERO,
|
||||
velocity:n,
|
||||
@@ -823,29 +825,29 @@ impl TouchingState{
|
||||
fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector<InternalInstruction,Time>,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,start_time:Time){
|
||||
// let relative_body=body.relative_to(&Body::ZERO);
|
||||
let relative_body=body;
|
||||
for contact in &self.contacts{
|
||||
for (convex_mesh_id,face_id) in &self.contacts{
|
||||
//detect face slide off
|
||||
let model_mesh=models.contact_mesh(&contact.convex_mesh_id);
|
||||
let model_mesh=models.contact_mesh(convex_mesh_id);
|
||||
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh());
|
||||
collector.collect(minkowski.predict_collision_face_out(&relative_body,start_time..collector.time(),contact.face_id).map(|(_face,time)|{
|
||||
collector.collect(minkowski.predict_collision_face_out(&relative_body,start_time..collector.time(),*face_id).map(|(_face,time)|{
|
||||
TimedInstruction{
|
||||
time:relative_body.time+time.into(),
|
||||
instruction:InternalInstruction::CollisionEnd(
|
||||
Collision::Contact(*contact),
|
||||
Collision::Contact(ContactCollision{face_id:*face_id,convex_mesh_id:*convex_mesh_id}),
|
||||
time
|
||||
),
|
||||
}
|
||||
}));
|
||||
}
|
||||
for intersect in &self.intersects{
|
||||
for convex_mesh_id in &self.intersects{
|
||||
//detect model collision in reverse
|
||||
let model_mesh=models.intersect_mesh(&intersect.convex_mesh_id);
|
||||
let model_mesh=models.intersect_mesh(convex_mesh_id);
|
||||
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh());
|
||||
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(
|
||||
Collision::Intersect(*intersect),
|
||||
Collision::Intersect(IntersectCollision{convex_mesh_id:*convex_mesh_id}),
|
||||
time
|
||||
),
|
||||
}
|
||||
@@ -1199,24 +1201,23 @@ impl<'a> PhysicsContext<'a>{
|
||||
//relative to moving platforms
|
||||
//let relative_body=state.body.relative_to(&Body::ZERO);
|
||||
let relative_body=&state.body;
|
||||
data.bvh.sample_aabb(&aabb,&mut |&convex_mesh_id|{
|
||||
data.bvh.sample_aabb(&aabb,&mut |convex_mesh_id|{
|
||||
if state.touching.contains(convex_mesh_id){
|
||||
return;
|
||||
}
|
||||
//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());
|
||||
collector.collect(minkowski.predict_collision_in(relative_body,state.time..collector.time())
|
||||
.and_then(|(face,dt)|{
|
||||
let collision=Collision::new(convex_mesh_id,face);
|
||||
// filter objects already in contacts
|
||||
(!state.touching.contains(&collision)).then(||
|
||||
TimedInstruction{
|
||||
time:relative_body.time+dt.into(),
|
||||
instruction:InternalInstruction::CollisionStart(
|
||||
collision,
|
||||
dt
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
.map(|(face,dt)|
|
||||
TimedInstruction{
|
||||
time:relative_body.time+dt.into(),
|
||||
instruction:InternalInstruction::CollisionStart(
|
||||
Collision::new(*convex_mesh_id,face),
|
||||
dt
|
||||
)
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
collector.take()
|
||||
@@ -1249,10 +1250,12 @@ fn recalculate_touching(
|
||||
//collision_end all existing contacts
|
||||
//I would have preferred while let Some(contact)=contacts.pop()
|
||||
//but there is no such method
|
||||
while let Some(&contact)=touching.contacts.iter().next(){
|
||||
while let Some((&convex_mesh_id,&face_id))=touching.contacts.iter().next(){
|
||||
let contact=ContactCollision{face_id,convex_mesh_id};
|
||||
collision_end_contact(move_state,body,touching,models,hitbox_mesh,style,camera,input_state,models.contact_attr(contact.convex_mesh_id.model_id),contact)
|
||||
}
|
||||
while let Some(&intersect)=touching.intersects.iter().next(){
|
||||
while let Some(&convex_mesh_id)=touching.intersects.iter().next(){
|
||||
let intersect=IntersectCollision{convex_mesh_id};
|
||||
collision_end_intersect(move_state,body,touching,models,hitbox_mesh,style,camera,input_state,mode,run,models.intersect_attr(intersect.convex_mesh_id.model_id),intersect,time);
|
||||
}
|
||||
//find all models in the teleport region
|
||||
@@ -1309,8 +1312,9 @@ fn set_position(
|
||||
fn set_velocity_cull(body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,v:Planar64Vec3)->bool{
|
||||
//This is not correct but is better than what I have
|
||||
let mut culled=false;
|
||||
touching.contacts.retain(|contact|{
|
||||
let n=contact_normal(models,hitbox_mesh,contact);
|
||||
touching.contacts.retain(|&convex_mesh_id,&mut face_id|{
|
||||
let contact=ContactCollision{face_id,convex_mesh_id};
|
||||
let n=contact_normal(models,hitbox_mesh,&contact);
|
||||
let r=n.dot(v).is_positive();
|
||||
if r{
|
||||
culled=true;
|
||||
@@ -1327,8 +1331,9 @@ fn set_velocity(body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hit
|
||||
fn set_acceleration_cull(body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,a:Planar64Vec3)->bool{
|
||||
//This is not correct but is better than what I have
|
||||
let mut culled=false;
|
||||
touching.contacts.retain(|contact|{
|
||||
let n=contact_normal(models,hitbox_mesh,contact);
|
||||
touching.contacts.retain(|&convex_mesh_id,&mut face_id|{
|
||||
let contact=ContactCollision{face_id,convex_mesh_id};
|
||||
let n=contact_normal(models,hitbox_mesh,&contact);
|
||||
let r=n.dot(a).is_positive();
|
||||
if r{
|
||||
culled=true;
|
||||
@@ -1681,7 +1686,7 @@ fn collision_end_contact(
|
||||
_attr:&gameplay_attributes::ContactAttributes,
|
||||
contact:ContactCollision,
|
||||
){
|
||||
touching.remove(&Collision::Contact(contact));//remove contact before calling contact_constrain_acceleration
|
||||
touching.contacts.remove(&contact.convex_mesh_id);//remove contact before calling contact_constrain_acceleration
|
||||
//check ground
|
||||
//TODO do better
|
||||
//this is inner code from move_state.cull_velocity
|
||||
@@ -1712,7 +1717,7 @@ fn collision_end_intersect(
|
||||
intersect:IntersectCollision,
|
||||
time:Time,
|
||||
){
|
||||
touching.remove(&Collision::Intersect(intersect));
|
||||
touching.intersects.remove(&intersect.convex_mesh_id);
|
||||
move_state.apply_enum_and_body(body,touching,models,hitbox_mesh,style,camera,input_state);
|
||||
if let Some(mode)=mode{
|
||||
let zone=mode.get_zone(intersect.convex_mesh_id.model_id.into());
|
||||
|
||||
Reference in New Issue
Block a user