use crate::physics::Body; use crate::model_physics::{VirtualMesh,FEV,FaceId}; use crate::integer::{Time,Planar64Vec3}; struct State{ fev:FEV, time:Time, } enum Transition{ Miss, Next(FEV,Time), Hit(FaceId,Time), } impl State{ fn next_transition(&self,mesh:&VirtualMesh,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. match &self.fev{ FEV::Face(face_id)=>{ //test own face collision time, ignoring edges with zero or conflicting derivative //test each edge collision time, ignoring edges with zero or conflicting derivative //if face: Transition::Hit(Face,Time) //if edge: Transition::NextState(State{time,fev:FEV::Edge(edge_id)}) //if none: Transition::Miss }, FEV::Edge(edge_id)=>{ //test each face collision time, ignoring faces with zero or conflicting derivative //test each vertex collision time, ignoring vertices with zero or conflicting derivative //if face: Transition::NextState(State{time,fev:FEV::Face(face_id)}) //if vert: Transition::NextState(State{time,fev:FEV::Vertex(vertex_id)}) //if none: Transition::Miss }, FEV::Vertex(vertex_id)=>{ //test each edge collision time, ignoring edges with zero or conflicting derivative //if some: Transition::NextState(State{time,fev:FEV::Edge(edge_id)}) //if none: Transition::Miss }, } } } pub fn predict_collision(mesh:&VirtualMesh,relative_body:&Body,time_limit:Time)->Option<(FaceId,Time)>{ let mut state=State{ time:relative_body.time, fev:mesh.closest_fev(relative_body.position), }; //it would be possible to write down the point of closest approach... loop{ match state.next_transition(mesh,relative_body,time_limit){ Transition::Miss=>return None, Transition::NextState(next_state)=>state=next_state, Transition::Hit(hit_face,hit_time)=>return Some((hit_face,hit_time)), } } }