diff --git a/src/model_physics.rs b/src/model_physics.rs index 7ca4256..bc190d4 100644 --- a/src/model_physics.rs +++ b/src/model_physics.rs @@ -751,6 +751,16 @@ impl MinkowskiMesh<'_>{ } best_edge.map(|e|(e.as_undirected(),best_time)) } + pub fn is_point_in_mesh(&self,point:Planar64Vec3)->bool{ + let infinity_body=crate::physics::Body::new(point,Planar64Vec3::Y,Planar64Vec3::ZERO,integer::Time::ZERO); + //movement must escape the mesh forwards and backwards in time, + //otherwise the point is not inside the mesh + self.predict_collision_out(&infinity_body,integer::Time::MAX) + .is_some_and(|_| + self.predict_collision_out(&-infinity_body,integer::Time::MAX) + .is_some() + ) + } } impl MeshQuery for MinkowskiMesh<'_>{ fn face_nd(&self,face_id:MinkowskiFace)->(Planar64Vec3,Planar64){ diff --git a/src/physics.rs b/src/physics.rs index 9caf231..ffe8f1b 100644 --- a/src/physics.rs +++ b/src/physics.rs @@ -1254,14 +1254,50 @@ fn contact_normal(models:&PhysicsModels,hitbox_mesh:&HitboxMesh,contact:&Contact minkowski.face_nd(contact.face_id).0 } +fn recalculate_touching( + state:&mut PhysicsState, + data:&PhysicsData, + models:&PhysicsModels, +){ + //drain all existing contacts + for contact in state.touching.contacts.drain(){ + collision_end_contact(state,data,models.contact_attr(contact.model_id),contact); + } + for intersect in state.touching.intersects.drain(){ + collision_end_intersect(state,data,models.intersect_attr(intersect.model_id),intersect); + } + //find all models in the teleport region + let mut aabb=aabb::Aabb::default(); + aabb.grow(state.body.position); + aabb.inflate(data.hitbox_mesh.halfsize); + //relative to moving platforms + //let relative_body=&VirtualBody::relative(&Body::default(),&state.body).body(state.time); + let relative_body=&state.body; + data.bvh.the_tester(&aabb,&mut |&convex_mesh_id|{ + //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()); + if minkowski.is_point_in_mesh(relative_body.position){ + match convex_mesh_id.model_id{ + //being inside of contact objects is an invalid physics state + //but the physics isn't advanced enough to do anything about it yet + //TODO: PushSolve and search for the closest valid position + PhysicsModelId::Contact(_)=>(), + PhysicsModelId::Intersect(model_id)=> + collision_start_intersect(state,data,data.models.intersect_attr(model_id),IntersectCollision{ + model_id, + submesh_id:convex_mesh_id.submesh_id, + }), + } + } + }); +} fn set_position(body:&mut Body,touching:&mut TouchingState,point:Planar64Vec3)->Planar64Vec3{ //test intersections at new position //hovering above the surface 0 units is not intersecting. you will fall into it just fine body.position=point; - //manual clear //for c in contacts{process_instruction(CollisionEnd(c))} - touching.clear(); - //TODO: calculate contacts and determine the actual state - //touching.recalculate(body); + //calculate contacts and determine the actual state + recalculate_touching(body); point } fn set_velocity_cull(body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,v:Planar64Vec3)->bool{