generic generic generic

This commit is contained in:
Quaternions 2023-10-27 14:18:50 -07:00
parent e1fde9b507
commit 72ebe5c9c8
2 changed files with 75 additions and 37 deletions

View File

@ -1,27 +1,27 @@
use crate::physics::Body; use crate::physics::Body;
use crate::model_physics::{VirtualMesh,FEV,FaceId}; use crate::model_physics::{FEV,MeshQuery};
use crate::integer::{Time,Planar64,Planar64Vec3}; use crate::integer::{Time,Planar64,Planar64Vec3};
use crate::zeroes::zeroes2; use crate::zeroes::zeroes2;
struct State{ struct State<FEV>{
fev:FEV, fev:FEV,
time:Time, time:Time,
} }
enum Transition{ enum Transition<F,E,V>{
Miss, Miss,
Next(FEV,Time), Next(FEV<F,E,V>,Time),
Hit(FaceId,Time), Hit(F,Time),
} }
impl State{ impl<F:Copy,E:Copy,V:Copy> State<FEV<F,E,V>>{
fn next_transition(&self,mesh:&VirtualMesh,body:&Body,time_limit:Time)->Transition{ 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 &self.fev{
&FEV::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
//n.a t^2+n.v t+n.p-d==0 //n.a t^2+n.v t+n.p-d==0
@ -40,14 +40,14 @@ impl State{
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 self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
best_time=t; best_time=t;
best_transtition=Transition::Next(FEV::Edge(edge_id),t); best_transtition=Transition::Next(FEV::<F,E,V>::Edge(edge_id),t);
break; break;
} }
} }
} }
//if none: //if none:
}, },
&FEV::Edge(edge_id)=>{ &FEV::<F,E,V>::Edge(edge_id)=>{
//test each face collision time, ignoring roots with zero or conflicting derivative //test each face collision time, ignoring roots with zero or conflicting derivative
for &test_face_id in mesh.edge_side_faces(edge_id){ for &test_face_id in mesh.edge_side_faces(edge_id){
let (n,d)=mesh.face_nd(test_face_id); let (n,d)=mesh.face_nd(test_face_id);
@ -55,7 +55,7 @@ impl State{
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 self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
best_time=t; best_time=t;
best_transtition=Transition::Next(FEV::Face(test_face_id),t); best_transtition=Transition::Next(FEV::<F,E,V>::Face(test_face_id),t);
break; break;
} }
} }
@ -67,14 +67,14 @@ impl State{
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 self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
best_time=t; best_time=t;
best_transtition=Transition::Next(FEV::Vert(vert_id),t); best_transtition=Transition::Next(FEV::<F,E,V>::Vert(vert_id),t);
break; break;
} }
} }
} }
//if none: //if none:
}, },
&FEV::Vert(vertex_id)=>{ &FEV::<F,E,V>::Vert(vertex_id)=>{
//test each edge collision time, ignoring roots with zero or conflicting derivative //test each edge collision time, ignoring roots with zero or conflicting derivative
for &(edge_id,test_face_id) in mesh.vert_edges(vertex_id){ for &(edge_id,test_face_id) in mesh.vert_edges(vertex_id){
let (n,d)=mesh.face_nd(test_face_id); let (n,d)=mesh.face_nd(test_face_id);
@ -82,7 +82,7 @@ impl State{
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 self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
best_time=t; best_time=t;
best_transtition=Transition::Next(FEV::Edge(edge_id),t); best_transtition=Transition::Next(FEV::<F,E,V>::Edge(edge_id),t);
break; break;
} }
} }
@ -94,7 +94,7 @@ impl State{
} }
} }
pub fn predict_collision(mesh:&VirtualMesh,relative_body:&Body,time_limit:Time)->Option<(FaceId,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{ let mut state=State{
fev:mesh.closest_fev(relative_body.position), fev:mesh.closest_fev(relative_body.position),
time:relative_body.time, time:relative_body.time,
@ -109,7 +109,7 @@ pub fn predict_collision(mesh:&VirtualMesh,relative_body:&Body,time_limit:Time)-
} }
} }
pub fn predict_collision_end(mesh:&VirtualMesh,relative_body:&Body,time_limit:Time,c:&crate::physics::RelativeCollision)->Option<(FaceId,Time)>{ pub fn predict_collision_end<F:Copy,E:Copy,V:Copy>(mesh:&impl MeshQuery<F,E,V>,relative_body:&Body,time_limit:Time,c:&crate::physics::RelativeCollision)->Option<(F,Time)>{
//imagine the mesh without the collision face //imagine the mesh without the collision face
//no algorithm needed, there is only one state and three cases (Face,Edge,None) //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 //determine when it passes an edge ("sliding off" case) or if it leaves the surface directly

View File

@ -8,10 +8,10 @@ pub struct EdgeId(usize);
pub struct FaceId(usize); pub struct FaceId(usize);
//Vertex <-> Edge <-> Face -> Collide //Vertex <-> Edge <-> Face -> Collide
pub enum FEV{ pub enum FEV<F,E,V>{
Face(FaceId), Face(F),
Edge(EdgeId), Edge(E),
Vert(VertId), Vert(V),
} }
//use Unit32 #[repr(C)] for map files //use Unit32 #[repr(C)] for map files
@ -19,6 +19,7 @@ struct Face{
normal:Planar64Vec3, normal:Planar64Vec3,
dot:Planar64, dot:Planar64,
} }
struct Vert(Planar64Vec3);
struct FaceRefs{ struct FaceRefs{
edges:Vec<(EdgeId,FaceId)>, edges:Vec<(EdgeId,FaceId)>,
verts:Vec<VertId>, verts:Vec<VertId>,
@ -32,25 +33,43 @@ struct VertRefs{
} }
pub struct PhysicsMesh{ pub struct PhysicsMesh{
faces:Vec<Face>, faces:Vec<Face>,
verts:Vec<Vert>,
face_topology:Vec<FaceRefs>, face_topology:Vec<FaceRefs>,
edge_topology:Vec<EdgeRefs>, edge_topology:Vec<EdgeRefs>,
vert_topology:Vec<VertRefs>, vert_topology:Vec<VertRefs>,
} }
impl PhysicsMesh{
pub fn face_nd(&self,face_id:FaceId)->(Planar64Vec3,Planar64){ pub trait MeshQuery<FACE,EDGE,VERT>{
fn closest_fev(&self,point:Planar64Vec3)->FEV<FACE,EDGE,VERT>;
fn face_nd(&self,face_id:FACE)->(Planar64Vec3,Planar64);
fn vert(&self,vert_id:VERT)->Planar64Vec3;
fn face_edges(&self,face_id:FACE)->&Vec<(EDGE,FACE)>;
fn edge_side_faces(&self,edge_id:EDGE)->&[FACE;2];
fn edge_ends(&self,edge_id:EDGE)->&[(VERT,FACE);2];
fn vert_edges(&self,vert_id:VERT)->&Vec<(EDGE,FACE)>;
}
impl MeshQuery<FaceId,EdgeId,VertId> for PhysicsMesh{
fn closest_fev(&self,point:Planar64Vec3)->FEV<FaceId,EdgeId,VertId>{
//put some genius code right here
todo!()
}
fn face_nd(&self,face_id:FaceId)->(Planar64Vec3,Planar64){
(self.faces[face_id.0].normal,self.faces[face_id.0].dot) (self.faces[face_id.0].normal,self.faces[face_id.0].dot)
} }
//ideally I never calculate the vertex position, but I have to for the graphical meshes... //ideally I never calculate the vertex position, but I have to for the graphical meshes...
pub fn face_edges(&self,face_id:FaceId)->&Vec<(EdgeId,FaceId)>{ fn vert(&self,vert_id:VertId)->Planar64Vec3{
todo!()
}
fn face_edges(&self,face_id:FaceId)->&Vec<(EdgeId,FaceId)>{
&self.face_topology[face_id.0].edges &self.face_topology[face_id.0].edges
} }
pub fn edge_side_faces(&self,edge_id:EdgeId)->&[FaceId;2]{ fn edge_side_faces(&self,edge_id:EdgeId)->&[FaceId;2]{
&self.edge_topology[edge_id.0].faces &self.edge_topology[edge_id.0].faces
} }
pub fn edge_ends(&self,edge_id:EdgeId)->&[(VertId,FaceId);2]{ fn edge_ends(&self,edge_id:EdgeId)->&[(VertId,FaceId);2]{
&self.edge_topology[edge_id.0].verts &self.edge_topology[edge_id.0].verts
} }
pub fn vert_edges(&self,vert_id:VertId)->&Vec<(EdgeId,FaceId)>{ fn vert_edges(&self,vert_id:VertId)->&Vec<(EdgeId,FaceId)>{
&self.vert_topology[vert_id.0].edges &self.vert_topology[vert_id.0].edges
} }
} }
@ -59,37 +78,56 @@ impl PhysicsMesh{
//(face,vertex) //(face,vertex)
//(edge,edge) //(edge,edge)
//(vertex,face) //(vertex,face)
#[derive(Clone,Copy)]
enum MinkowskiVert{
VertVert(VertId,VertId),
}
#[derive(Clone,Copy)]
enum MinkowskiEdge{
VertEdge(VertId,EdgeId),
EdgeVert(EdgeId,VertId),
}
#[derive(Clone,Copy)]
enum MinkowskiFace{
FaceVert(FaceId,VertId),
EdgeEdge(EdgeId,EdgeId),
VertFace(VertId,FaceId),
}
pub struct VirtualMesh<'a>{ pub struct MinkowskiMesh<'a>{
mesh0:&'a PhysicsMesh, mesh0:&'a PhysicsMesh,
mesh1:&'a PhysicsMesh, mesh1:&'a PhysicsMesh,
} }
impl VirtualMesh<'_>{ impl MinkowskiMesh<'_>{
pub fn minkowski_sum<'a>(mesh0:&'a PhysicsMesh,mesh1:&'a PhysicsMesh)->VirtualMesh<'a>{ pub fn minkowski_sum<'a>(mesh0:&'a PhysicsMesh,mesh1:&'a PhysicsMesh)->MinkowskiMesh<'a>{
VirtualMesh{ MinkowskiMesh{
mesh0, mesh0,
mesh1, mesh1,
} }
} }
pub fn closest_fev(&self,point:Planar64Vec3)->FEV{ }
impl MeshQuery<MinkowskiFace,MinkowskiEdge,MinkowskiVert> for MinkowskiMesh<'_>{
fn closest_fev(&self,point:Planar64Vec3)->FEV<MinkowskiFace,MinkowskiEdge,MinkowskiVert>{
//put some genius code right here //put some genius code right here
todo!() todo!()
} }
pub fn face_nd(&self,face_id:FaceId)->(Planar64Vec3,Planar64){ fn face_nd(&self,face_id:MinkowskiFace)->(Planar64Vec3,Planar64){
todo!() todo!()
} }
//ideally I never calculate the vertex position, but I have to for the graphical meshes... fn vert(&self,vert_id:MinkowskiVert)->Planar64Vec3{
pub fn face_edges(&self,face_id:FaceId)->&Vec<(EdgeId,FaceId)>{
todo!() todo!()
} }
pub fn edge_side_faces(&self,edge_id:EdgeId)->&[FaceId;2]{ fn face_edges(&self,face_id:MinkowskiFace)->&Vec<(MinkowskiEdge,MinkowskiFace)>{
todo!() todo!()
} }
pub fn edge_ends(&self,edge_id:EdgeId)->&[(VertId,FaceId);2]{ fn edge_side_faces(&self,edge_id:MinkowskiEdge)->&[MinkowskiFace;2]{
todo!() todo!()
} }
pub fn vert_edges(&self,vert_id:VertId)->&Vec<(EdgeId,FaceId)>{ fn edge_ends(&self,edge_id:MinkowskiEdge)->&[(MinkowskiVert,MinkowskiFace);2]{
todo!()
}
fn vert_edges(&self,vert_id:MinkowskiVert)->&Vec<(MinkowskiEdge,MinkowskiFace)>{
todo!() todo!()
} }
} }