forked from StrafesNET/strafe-client
implement MinkowskiMesh::predict_collision{_end}
This commit is contained in:
parent
2d3efdc2e1
commit
5bfd340d87
@ -3,24 +3,18 @@ use crate::model_physics::{FEV,MeshQuery};
|
|||||||
use crate::integer::{Time,Planar64};
|
use crate::integer::{Time,Planar64};
|
||||||
use crate::zeroes::zeroes2;
|
use crate::zeroes::zeroes2;
|
||||||
|
|
||||||
struct State<FEV>{
|
|
||||||
fev:FEV,
|
|
||||||
time:Time,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Transition<F,E,V>{
|
enum Transition<F,E,V>{
|
||||||
Miss,
|
Miss,
|
||||||
Next(FEV<F,E,V>,Time),
|
Next(FEV<F,E,V>,Time),
|
||||||
Hit(F,Time),
|
Hit(F,Time),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F:Copy,E:Copy,V:Copy> State<FEV<F,E,V>>{
|
pub fn next_transition_body<F:Copy,E:Copy,V:Copy>(fev:&FEV<F,E,V>,time:Time,mesh:&impl MeshQuery<F,E,V>,body:&Body,time_limit:Time)->Transition<F,E,V>{
|
||||||
fn next_transition(&self,mesh:&impl MeshQuery<F,E,V>,body:&Body,time_limit:Time)->Transition<F,E,V>{
|
|
||||||
//conflicting derivative means it crosses in the wrong direction.
|
//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.
|
//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_time=time_limit;
|
||||||
let mut best_transtition=Transition::Miss;
|
let mut best_transtition=Transition::Miss;
|
||||||
match &self.fev{
|
match fev{
|
||||||
&FEV::<F,E,V>::Face(face_id)=>{
|
&FEV::<F,E,V>::Face(face_id)=>{
|
||||||
//test own face collision time, ignoring roots with zero or conflicting derivative
|
//test own face collision time, ignoring roots with zero or conflicting derivative
|
||||||
//n=face.normal d=face.dot
|
//n=face.normal d=face.dot
|
||||||
@ -28,7 +22,7 @@ impl<F:Copy,E:Copy,V:Copy> State<FEV<F,E,V>>{
|
|||||||
let (n,d)=mesh.face_nd(face_id);
|
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)){
|
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);
|
let t=body.time+Time::from(t);
|
||||||
if self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
if time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
||||||
best_time=t;
|
best_time=t;
|
||||||
best_transtition=Transition::Hit(face_id,t);
|
best_transtition=Transition::Hit(face_id,t);
|
||||||
}
|
}
|
||||||
@ -41,7 +35,7 @@ impl<F:Copy,E:Copy,V:Copy> State<FEV<F,E,V>>{
|
|||||||
let d=n.dot(mesh.vert(mesh.edge_verts(edge_id)[0]));
|
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)){
|
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);
|
let t=body.time+Time::from(t);
|
||||||
if self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
if time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
||||||
best_time=t;
|
best_time=t;
|
||||||
best_transtition=Transition::Next(FEV::<F,E,V>::Edge(edge_id),t);
|
best_transtition=Transition::Next(FEV::<F,E,V>::Edge(edge_id),t);
|
||||||
break;
|
break;
|
||||||
@ -59,7 +53,7 @@ impl<F:Copy,E:Copy,V:Copy> State<FEV<F,E,V>>{
|
|||||||
let d=n.dot(mesh.vert(mesh.edge_verts(edge_id)[0]));
|
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)){
|
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);
|
let t=body.time+Time::from(t);
|
||||||
if self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
if time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
||||||
best_time=t;
|
best_time=t;
|
||||||
best_transtition=Transition::Next(FEV::<F,E,V>::Face(test_face_id),t);
|
best_transtition=Transition::Next(FEV::<F,E,V>::Face(test_face_id),t);
|
||||||
break;
|
break;
|
||||||
@ -72,7 +66,7 @@ impl<F:Copy,E:Copy,V:Copy> State<FEV<F,E,V>>{
|
|||||||
let d=n.dot(mesh.vert(vert_id));
|
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)){
|
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);
|
let t=body.time+Time::from(t);
|
||||||
if self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
if time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
||||||
best_time=t;
|
best_time=t;
|
||||||
best_transtition=Transition::Next(FEV::<F,E,V>::Vert(vert_id),t);
|
best_transtition=Transition::Next(FEV::<F,E,V>::Vert(vert_id),t);
|
||||||
break;
|
break;
|
||||||
@ -88,7 +82,7 @@ impl<F:Copy,E:Copy,V:Copy> State<FEV<F,E,V>>{
|
|||||||
let d=n.dot(mesh.vert(vert_id));
|
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)){
|
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);
|
let t=body.time+Time::from(t);
|
||||||
if self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
if time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
|
||||||
best_time=t;
|
best_time=t;
|
||||||
best_transtition=Transition::Next(FEV::<F,E,V>::Edge(edge_id),t);
|
best_transtition=Transition::Next(FEV::<F,E,V>::Edge(edge_id),t);
|
||||||
break;
|
break;
|
||||||
@ -100,27 +94,13 @@ impl<F:Copy,E:Copy,V:Copy> State<FEV<F,E,V>>{
|
|||||||
}
|
}
|
||||||
best_transtition
|
best_transtition
|
||||||
}
|
}
|
||||||
}
|
pub fn crawl_fev_body<F:Copy,E:Copy,V:Copy>(mut fev:FEV<F,E,V>,mesh:&impl MeshQuery<F,E,V>,relative_body:&Body,time_limit:Time)->Option<(F,Time)>{
|
||||||
|
let mut time=relative_body.time;
|
||||||
pub fn predict_collision<F:Copy,E:Copy,V:Copy>(mesh:&impl MeshQuery<F,E,V>,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...
|
|
||||||
loop{
|
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::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)),
|
Transition::Hit(face,time)=>return Some((face,time)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn predict_collision_end<F:Copy,E:Copy,V:Copy>(mesh:&impl MeshQuery<F,E,V>,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
|
|
||||||
}
|
|
||||||
|
@ -325,6 +325,31 @@ impl MinkowskiMesh<'_>{
|
|||||||
//put some genius code right here
|
//put some genius code right here
|
||||||
todo!()
|
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<t&&t<best_time&&n.dot(relative_body.extrapolated_velocity(t))<Planar64::ZERO{
|
||||||
|
best_time=t;
|
||||||
|
best_edge=Some(edge_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
best_edge.map(|e|(e,best_time))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl MeshQuery<MinkowskiFace,MinkowskiEdge,MinkowskiVert> for MinkowskiMesh<'_>{
|
impl MeshQuery<MinkowskiFace,MinkowskiEdge,MinkowskiVert> for MinkowskiMesh<'_>{
|
||||||
fn face_nd(&self,face_id:MinkowskiFace)->(Planar64Vec3,Planar64){
|
fn face_nd(&self,face_id:MinkowskiFace)->(Planar64Vec3,Planar64){
|
||||||
|
Loading…
Reference in New Issue
Block a user