diff --git a/src/face_crawler.rs b/src/face_crawler.rs index 663384c..63915bb 100644 --- a/src/face_crawler.rs +++ b/src/face_crawler.rs @@ -3,24 +3,18 @@ use crate::model_physics::{FEV,MeshQuery}; use crate::integer::{Time,Planar64}; use crate::zeroes::zeroes2; -struct State{ - fev:FEV, - time:Time, -} - enum Transition{ Miss, Next(FEV,Time), Hit(F,Time), } -impl State>{ - fn next_transition(&self,mesh:&impl MeshQuery,body:&Body,time_limit:Time)->Transition{ + pub fn next_transition_body(fev:&FEV,time:Time,mesh:&impl MeshQuery,body:&Body,time_limit:Time)->Transition{ //conflicting derivative means it crosses in the wrong direction. //if the transition time is equal to an already tested transition, do not replace the current best. let mut best_time=time_limit; let mut best_transtition=Transition::Miss; - match &self.fev{ + match fev{ &FEV::::Face(face_id)=>{ //test own face collision time, ignoring roots with zero or conflicting derivative //n=face.normal d=face.dot @@ -28,7 +22,7 @@ impl State>{ let (n,d)=mesh.face_nd(face_id); for t in zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){ let t=body.time+Time::from(t); - if self.time State>{ let d=n.dot(mesh.vert(mesh.edge_verts(edge_id)[0])); for t in zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){ let t=body.time+Time::from(t); - if self.time::Edge(edge_id),t); break; @@ -59,7 +53,7 @@ impl State>{ let d=n.dot(mesh.vert(mesh.edge_verts(edge_id)[0])); for t in zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){ let t=body.time+Time::from(t); - if self.time::Face(test_face_id),t); break; @@ -72,7 +66,7 @@ impl State>{ let d=n.dot(mesh.vert(vert_id)); for t in zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){ let t=body.time+Time::from(t); - if self.time::Vert(vert_id),t); break; @@ -88,7 +82,7 @@ impl State>{ let d=n.dot(mesh.vert(vert_id)); for t in zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){ let t=body.time+Time::from(t); - if self.time::Edge(edge_id),t); break; @@ -100,27 +94,13 @@ impl State>{ } best_transtition } -} - -pub fn predict_collision(mesh:&impl MeshQuery,relative_body:&Body,time_limit:Time)->Option<(F,Time)>{ - let mut state=State{ - fev:mesh.closest_fev(relative_body.position), - time:relative_body.time, - }; - //it would be possible to write down the point of closest approach... +pub fn crawl_fev_body(mut fev:FEV,mesh:&impl MeshQuery,relative_body:&Body,time_limit:Time)->Option<(F,Time)>{ + let mut time=relative_body.time; loop{ - match state.next_transition(mesh,relative_body,time_limit){ + match next_transition_body(&fev,time,mesh,relative_body,time_limit){ Transition::Miss=>return None, - Transition::Next(fev,time)=>(state.fev,state.time)=(fev,time), + Transition::Next(next_fev,next_time)=>(fev,time)=(next_fev,next_time), Transition::Hit(face,time)=>return Some((face,time)), } } } - -pub fn predict_collision_end(mesh:&impl MeshQuery,relative_body:&Body,time_limit:Time,ignore_face_id:F)->Option<(F,Time)>{ - //imagine the mesh without the collision face - //no algorithm needed, there is only one state and three cases (Face,Edge,None) - //determine when it passes an edge ("sliding off" case) or if it leaves the surface directly - //the state can be constructed from the ContactCollision directly - None -} diff --git a/src/model_physics.rs b/src/model_physics.rs index a3cc277..8b16801 100644 --- a/src/model_physics.rs +++ b/src/model_physics.rs @@ -325,6 +325,31 @@ impl MinkowskiMesh<'_>{ //put some genius code right here todo!() } + pub fn predict_collision(&self,relative_body:&crate::physics::Body,time_limit:crate::integer::Time)->Option<(MinkowskiFace,crate::integer::Time)>{ + crate::face_crawler::crawl_fev_body(self.closest_fev(relative_body.position),self,relative_body,time_limit) + } + pub fn predict_collision_end(&self,relative_body:&crate::physics::Body,time_limit:crate::integer::Time,contact_face_id:MinkowskiFace)->Option<(MinkowskiEdge,crate::integer::Time)>{ + //no algorithm needed, there is only one state and two cases (Edge,None) + //determine when it passes an edge ("sliding off" case) + let mut best_time=time_limit; + let mut best_edge=None; + let face_n=self.face_nd(contact_face_id).0; + for &edge_id in self.face_edges(contact_face_id).iter(){ + let edge_n=self.edge_n(edge_id); + let n=face_n.cross(edge_n); + //picking a vert randomly is terrible + let d=n.dot(self.vert(self.edge_verts(edge_id)[0])); + for t in crate::zeroes::zeroes2((n.dot(relative_body.position)-d)*2,n.dot(relative_body.velocity)*2,n.dot(relative_body.acceleration)){ + let t=relative_body.time+crate::integer::Time::from(t); + if relative_body.time for MinkowskiMesh<'_>{ fn face_nd(&self,face_id:MinkowskiFace)->(Planar64Vec3,Planar64){