convert to fev using dumbest algorithm possible

This commit is contained in:
2025-11-27 10:59:33 -08:00
parent 4ff62cc991
commit 18c73b12d8
2 changed files with 64 additions and 10 deletions

View File

@@ -2,12 +2,13 @@ use strafesnet_common::integer::vec3;
use strafesnet_common::integer::vec3::Vector3;
use strafesnet_common::integer::{Fixed,Planar64Vec3};
use crate::model::{MeshQuery,MinkowskiMesh,MinkowskiVert};
use crate::model::{DirectedEdge,FEV,MeshQuery,MinkowskiMesh,MinkowskiVert};
// This algorithm is based on Lua code
// written by Trey Reynolds in 2021
type Simplex<const N:usize>=[MinkowskiVert;N];
#[derive(Clone,Copy)]
enum Simplex1_3{
Simplex1(Simplex<1>),
Simplex2(Simplex<2>),
@@ -546,7 +547,7 @@ pub fn contains_point(mesh:&MinkowskiMesh,point:Planar64Vec3)->bool{
// TODO: remove mesh negation
minimum_difference::<ENABLE_FAST_FAIL,_>(&-mesh,point,
// on_exact
|last_pos,direction|{
|_simplex,last_pos,direction|{
// local norm = direction.unit
// local dist = a:Dot(norm)
// local hits = -dist < radiusP + radiusQ
@@ -562,17 +563,61 @@ pub fn contains_point(mesh:&MinkowskiMesh,point:Planar64Vec3)->bool{
||false
)
}
pub fn closest_fev(mesh:&MinkowskiMesh,point:Planar64Vec3)->Topology{
#[derive(Debug)]
pub struct OhNoes;
pub fn closest_fev_not_inside<'a>(mesh:&MinkowskiMesh<'a>,point:Planar64Vec3)->Option<Result<FEV<MinkowskiMesh<'a>>,OhNoes>>{
const ENABLE_FAST_FAIL:bool=false;
// TODO: remove mesh negation
minimum_difference::<ENABLE_FAST_FAIL,_>(&-mesh,point,
// on_exact
|_last_pos,_direction|unimplemented!(),
|simplex,_last_pos,_direction|{
// Convert simplex to FEV
// Vertices must be inverted since the mesh is inverted
Some(match simplex{
Simplex1_3::Simplex1([v0])=>Ok(FEV::Vert(-v0)),
Simplex1_3::Simplex2([v0,v1])=>{
// invert
let (v0,v1)=(-v0,-v1);
// dumbest stupidest brute force search
let v0e=mesh.vert_edges(v0);
for &v0e in v0e.as_ref(){
// check opposite vertex to see if it is v1
if mesh.edge_verts(v0e.as_undirected()).as_ref()[v0e.parity() as usize]==v1{
return Some(Ok(FEV::Edge(v0e.as_undirected())));
}
}
Err(OhNoes)
},
Simplex1_3::Simplex3([v0,v1,v2])=>{
// invert
let (v0,v1,v2)=(-v0,-v1,-v2);
// dumbest stupidest brute force search
let v0e=mesh.vert_edges(v0);
for &v0e in v0e.as_ref(){
// check opposite vertex to see if it is v1
if mesh.edge_verts(v0e.as_undirected()).as_ref()[v0e.parity() as usize]==v1{
// check if a vertex of the face is v2
let ef=mesh.edge_faces(v0e.as_undirected());
for &ef in ef.as_ref(){
let fe=mesh.face_edges(ef);
for e in fe.as_ref(){
if mesh.edge_verts(e.as_undirected()).as_ref()[e.parity() as usize]==v2{
return Some(Ok(FEV::Face(ef)));
}
}
}
}
}
Err(OhNoes)
},
})
},
// on_escape
|simplex|{
|_simplex|{
// intersection is guaranteed at this point
// local norm, dist, u0, u1, v0, v1, w0, w1 = expand(queryP, queryQ, a0, a1, b0, b1, c0, c1, d0, d1, 1e-5)
let simplex=refine_to_exact(mesh,simplex);
Topology{simplex}
// let simplex=refine_to_exact(mesh,simplex);
None
},
// fast_fail value is irrelevant and will never be returned!
||unreachable!()
@@ -587,7 +632,7 @@ pub fn closest_fev(mesh:&MinkowskiMesh,point:Planar64Vec3)->Topology{
fn minimum_difference<const ENABLE_FAST_FAIL:bool,T>(
mesh:&MinkowskiMesh,
point:Planar64Vec3,
on_exact:impl FnOnce(Planar64Vec3,Planar64Vec3)->T,
on_exact:impl FnOnce(Simplex1_3,Planar64Vec3,Planar64Vec3)->T,
on_escape:impl FnOnce(Simplex<4>)->T,
on_fast_fail:impl FnOnce()->T,
)->T{
@@ -627,7 +672,7 @@ fn minimum_difference<const ENABLE_FAST_FAIL:bool,T>(
if !direction.dot(next_pos-last_pos).is_positive()
||simplex_big.det_is_zero(mesh){
// Found enough information to compute the exact closest point.
return on_exact(last_pos,direction);
return on_exact(simplex_small,last_pos,direction);
}
// direction, a0, a1, b0, b1, c0, c1, d0, d1 = reduceSimplex(new_point_p, new_point_q, a0, a1, b0, b1, c0, c1)

View File

@@ -571,7 +571,16 @@ impl MeshQuery for TransformedMesh<'_>{
pub enum MinkowskiVert{
VertVert(SubmeshVertId,SubmeshVertId),
}
#[derive(Clone,Copy,Debug)]
// TODO: remove this
impl core::ops::Neg for MinkowskiVert{
type Output=Self;
fn neg(self)->Self::Output{
match self{
MinkowskiVert::VertVert(v0,v1)=>MinkowskiVert::VertVert(v1,v0),
}
}
}
#[derive(Clone,Copy,Debug,Eq,PartialEq)]
pub enum MinkowskiEdge{
VertEdge(SubmeshVertId,SubmeshEdgeId),
EdgeVert(SubmeshEdgeId,SubmeshVertId),