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::model_physics::{VirtualMesh,FEV,FaceId};
use crate::model_physics::{FEV,MeshQuery};
use crate::integer::{Time,Planar64,Planar64Vec3};
use crate::zeroes::zeroes2;
struct State{
struct State<FEV>{
fev:FEV,
time:Time,
}
enum Transition{
enum Transition<F,E,V>{
Miss,
Next(FEV,Time),
Hit(FaceId,Time),
Next(FEV<F,E,V>,Time),
Hit(F,Time),
}
impl State{
fn next_transition(&self,mesh:&VirtualMesh,body:&Body,time_limit:Time)->Transition{
impl<F:Copy,E:Copy,V:Copy> State<FEV<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.
//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{
&FEV::Face(face_id)=>{
&FEV::<F,E,V>::Face(face_id)=>{
//test own face collision time, ignoring roots with zero or conflicting derivative
//n=face.normal d=face.dot
//n.a t^2+n.v t+n.p-d==0
@ -40,14 +40,14 @@ impl State{
let t=body.time+Time::from(t);
if self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
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;
}
}
}
//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
for &test_face_id in mesh.edge_side_faces(edge_id){
let (n,d)=mesh.face_nd(test_face_id);
@ -55,7 +55,7 @@ impl State{
let t=body.time+Time::from(t);
if self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
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;
}
}
@ -67,14 +67,14 @@ impl State{
let t=body.time+Time::from(t);
if self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
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;
}
}
}
//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
for &(edge_id,test_face_id) in mesh.vert_edges(vertex_id){
let (n,d)=mesh.face_nd(test_face_id);
@ -82,7 +82,7 @@ impl State{
let t=body.time+Time::from(t);
if self.time<t&&t<best_time&&n.dot(body.extrapolated_velocity(t))<Planar64::ZERO{
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;
}
}
@ -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{
fev:mesh.closest_fev(relative_body.position),
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
//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

View File

@ -8,10 +8,10 @@ pub struct EdgeId(usize);
pub struct FaceId(usize);
//Vertex <-> Edge <-> Face -> Collide
pub enum FEV{
Face(FaceId),
Edge(EdgeId),
Vert(VertId),
pub enum FEV<F,E,V>{
Face(F),
Edge(E),
Vert(V),
}
//use Unit32 #[repr(C)] for map files
@ -19,6 +19,7 @@ struct Face{
normal:Planar64Vec3,
dot:Planar64,
}
struct Vert(Planar64Vec3);
struct FaceRefs{
edges:Vec<(EdgeId,FaceId)>,
verts:Vec<VertId>,
@ -32,25 +33,43 @@ struct VertRefs{
}
pub struct PhysicsMesh{
faces:Vec<Face>,
verts:Vec<Vert>,
face_topology:Vec<FaceRefs>,
edge_topology:Vec<EdgeRefs>,
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)
}
//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
}
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
}
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
}
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
}
}
@ -59,37 +78,56 @@ impl PhysicsMesh{
//(face,vertex)
//(edge,edge)
//(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,
mesh1:&'a PhysicsMesh,
}
impl VirtualMesh<'_>{
pub fn minkowski_sum<'a>(mesh0:&'a PhysicsMesh,mesh1:&'a PhysicsMesh)->VirtualMesh<'a>{
VirtualMesh{
impl MinkowskiMesh<'_>{
pub fn minkowski_sum<'a>(mesh0:&'a PhysicsMesh,mesh1:&'a PhysicsMesh)->MinkowskiMesh<'a>{
MinkowskiMesh{
mesh0,
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
todo!()
}
pub fn face_nd(&self,face_id:FaceId)->(Planar64Vec3,Planar64){
fn face_nd(&self,face_id:MinkowskiFace)->(Planar64Vec3,Planar64){
todo!()
}
//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:MinkowskiVert)->Planar64Vec3{
todo!()
}
pub fn edge_side_faces(&self,edge_id:EdgeId)->&[FaceId;2]{
fn face_edges(&self,face_id:MinkowskiFace)->&Vec<(MinkowskiEdge,MinkowskiFace)>{
todo!()
}
pub fn edge_ends(&self,edge_id:EdgeId)->&[(VertId,FaceId);2]{
fn edge_side_faces(&self,edge_id:MinkowskiEdge)->&[MinkowskiFace;2]{
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!()
}
}