Compare commits
5 Commits
rewrite-ph
...
bug13-proc
| Author | SHA1 | Date | |
|---|---|---|---|
|
c5922bf2b7
|
|||
|
ff990e1d9f
|
|||
|
e4f3418bc6
|
|||
|
6ca6d5e484
|
|||
|
0668ac2def
|
@@ -74,13 +74,13 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
||||
where
|
||||
// This is hardcoded for MinkowskiMesh lol
|
||||
M::Face:Copy,
|
||||
M::Edge:Copy,
|
||||
M::Vert:Copy,
|
||||
M::Edge:Copy+core::fmt::Debug,
|
||||
M::Vert:Copy+core::fmt::Debug,
|
||||
F:core::ops::Mul<Fixed<1,32>,Output=Fixed<4,128>>,
|
||||
<F as core::ops::Mul<Fixed<1,32>>>::Output:core::iter::Sum,
|
||||
M::Offset:core::ops::Sub<<F as std::ops::Mul<Fixed<1,32>>>::Output>,
|
||||
{
|
||||
fn next_transition(&self,mesh:&M,body:&Body,lower_bound:Bound<GigaTime>,mut upper_bound:Bound<GigaTime>)->Transition<M>{
|
||||
fn next_transition<const ENABLE_DEBUG:bool>(&self,mesh:&M,body:&Body,lower_bound:Bound<GigaTime>,mut upper_bound:Bound<GigaTime>)->Transition<M>{
|
||||
//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_transition=Transition::Miss;
|
||||
@@ -132,6 +132,9 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
||||
//wrap for speed
|
||||
for dt in Fixed::<4,128>::zeroes2(n.dot(delta_pos).wrap_4(),n.dot(body.velocity).wrap_4()*2,n.dot(body.acceleration).wrap_4()){
|
||||
if low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||
if ENABLE_DEBUG{
|
||||
println!("Face Crawler FEV::Edge({edge_id:?}) -> FEV::Face");
|
||||
}
|
||||
upper_bound=Bound::Included(dt);
|
||||
best_transition=Transition::Next(FEV::Face(edge_face_id),dt);
|
||||
break;
|
||||
@@ -160,6 +163,9 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
||||
let n=-mesh.directed_edge_n(directed_edge_id);
|
||||
for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){
|
||||
if low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){
|
||||
if ENABLE_DEBUG{
|
||||
println!("Face Crawler FEV::Vert({vert_id:?}) -> FEV::Edge");
|
||||
}
|
||||
let dt=Ratio::new(dt.num.widen_4(),dt.den.widen_4());
|
||||
upper_bound=Bound::Included(dt);
|
||||
best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt);
|
||||
@@ -172,11 +178,11 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M>
|
||||
}
|
||||
best_transition
|
||||
}
|
||||
pub fn crawl(mut self,mesh:&M,relative_body:&Body,lower_bound:Bound<&Time>,upper_bound:Bound<&Time>)->CrawlResult<M>{
|
||||
pub fn crawl<const ENABLE_DEBUG:bool>(mut self,mesh:&M,relative_body:&Body,lower_bound:Bound<&Time>,upper_bound:Bound<&Time>)->CrawlResult<M>{
|
||||
let mut lower_bound=lower_bound.map(|&t|into_giga_time(t,relative_body.time));
|
||||
let upper_bound=upper_bound.map(|&t|into_giga_time(t,relative_body.time));
|
||||
for _ in 0..20{
|
||||
match self.next_transition(mesh,relative_body,lower_bound,upper_bound){
|
||||
match self.next_transition::<ENABLE_DEBUG>(mesh,relative_body,lower_bound,upper_bound){
|
||||
Transition::Miss=>return CrawlResult::Miss(self),
|
||||
Transition::Next(next_fev,next_time)=>(self,lower_bound)=(next_fev,Bound::Included(next_time)),
|
||||
Transition::Hit(face,time)=>return CrawlResult::Hit(face,time),
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
mod body;
|
||||
mod face_crawler;
|
||||
mod mesh_query;
|
||||
mod minkowski;
|
||||
mod model;
|
||||
mod push_solve;
|
||||
mod face_crawler;
|
||||
mod model;
|
||||
|
||||
pub mod physics;
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
pub struct Vert<VertId>(pub VertId);
|
||||
pub struct Edge<VertId>(pub VertId,pub VertId);
|
||||
pub struct Face<VertId>(pub VertId,pub VertId,pub VertId);
|
||||
|
||||
pub enum FEV<VertId>{
|
||||
Vert(Vert<VertId>),
|
||||
Edge(Edge<VertId>),
|
||||
Face(Face<VertId>),
|
||||
}
|
||||
|
||||
pub trait MeshTopology{
|
||||
type VertId;
|
||||
fn for_each_vert_edge(&self,vert_id:Vert<Self::VertId>,f:impl FnMut(Edge<Self::VertId>));
|
||||
fn for_each_vert_face(&self,vert_id:Vert<Self::VertId>,f:impl FnMut(Face<Self::VertId>));
|
||||
fn edge_faces(&self,edge_id:Edge<Self::VertId>)->impl AsRef<[Face<Self::VertId>;2]>;
|
||||
fn edge_verts(&self,edge_id:Edge<Self::VertId>)->impl AsRef<[Vert<Self::VertId>;2]>;
|
||||
fn for_each_face_vert(&self,face_id:Face<Self::VertId>,f:impl FnMut(Vert<Self::VertId>));
|
||||
fn for_each_face_edge(&self,face_id:Face<Self::VertId>,f:impl FnMut(Edge<Self::VertId>));
|
||||
}
|
||||
|
||||
// Make face_nd d value relative
|
||||
// euclidean point?
|
||||
// Simplex physics
|
||||
// Directed edge nucessary?
|
||||
// recursive for_each function calls
|
||||
// define faces from vertices (Fixed<2> vs Fixed<3>)
|
||||
pub trait MeshQuery:MeshTopology{
|
||||
type Position;
|
||||
type Normal;
|
||||
type Offset;
|
||||
fn vert(&self,vert_id:Vert<Self::VertId>)->Self::Position;
|
||||
/// This must return a point inside the mesh.
|
||||
fn hint_point(&self)->Self::Position;
|
||||
fn face_nd(&self,face_id:Face<Self::VertId>)->(Self::Normal,Self::Offset);
|
||||
fn edge_n(&self,edge_id:Edge<Self::VertId>)->Self::Position;
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
use crate::mesh_query::{MeshQuery,MeshTopology};
|
||||
use crate::mesh_query::{Face,Edge,Vert};
|
||||
|
||||
struct AsRefHelper<T>(T);
|
||||
impl<T> AsRef<T> for AsRefHelper<T>{
|
||||
fn as_ref(&self)->&T{
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MinkowskiVert<V>{
|
||||
vert0:V,
|
||||
vert1:V,
|
||||
}
|
||||
|
||||
pub struct Minkowski<M>{
|
||||
mesh0:M,
|
||||
mesh1:M,
|
||||
}
|
||||
|
||||
impl<M> Minkowski<M>{
|
||||
pub fn sum(mesh0:M,mesh1:M)->Self{
|
||||
Self{mesh0,mesh1}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M:MeshTopology> MeshTopology for Minkowski<M>{
|
||||
type VertId=MinkowskiVert<M::VertId>;
|
||||
fn for_each_vert_edge(&self,vert_id:Vert<Self::VertId>,f:impl FnMut(Edge<Self::VertId>)){
|
||||
todo!()
|
||||
}
|
||||
fn for_each_vert_face(&self,vert_id:Vert<Self::VertId>,f:impl FnMut(Face<Self::VertId>)){
|
||||
todo!()
|
||||
}
|
||||
fn edge_faces(&self,edge_id:Edge<Self::VertId>)->impl AsRef<[Face<Self::VertId>;2]>{
|
||||
AsRefHelper(todo!())
|
||||
}
|
||||
fn edge_verts(&self,edge_id:Edge<Self::VertId>)->impl AsRef<[Vert<Self::VertId>;2]>{
|
||||
AsRefHelper(todo!())
|
||||
}
|
||||
fn for_each_face_vert(&self,face_id:Face<Self::VertId>,f:impl FnMut(Vert<Self::VertId>)){
|
||||
todo!()
|
||||
}
|
||||
fn for_each_face_edge(&self,face_id:Face<Self::VertId>,f:impl FnMut(Edge<Self::VertId>)){
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
use strafesnet_common::integer::vec3::Vector3;
|
||||
use strafesnet_common::integer::Fixed;
|
||||
impl<M> MeshQuery for Minkowski<M>
|
||||
where
|
||||
M:MeshQuery<
|
||||
Position=Vector3<Fixed<1,32>>,
|
||||
Normal=Vector3<Fixed<3,96>>,
|
||||
Offset=Fixed<4,128>,
|
||||
>
|
||||
{
|
||||
type Position=M::Position;
|
||||
type Normal=M::Normal;
|
||||
type Offset=M::Offset;
|
||||
fn vert(&self,vert_id:Vert<Self::VertId>)->Self::Position{
|
||||
let Vert(MinkowskiVert{vert0,vert1})=vert_id;
|
||||
self.mesh1.vert(Vert(vert1))-self.mesh0.vert(Vert(vert0))
|
||||
}
|
||||
fn hint_point(&self)->Self::Position{
|
||||
self.mesh1.hint_point()-self.mesh0.hint_point()
|
||||
}
|
||||
fn face_nd(&self,face_id:Face<Self::VertId>)->(Self::Normal,Self::Offset){
|
||||
todo!()
|
||||
}
|
||||
fn edge_n(&self,edge_id:Edge<Self::VertId>)->Self::Position{
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -91,6 +91,7 @@ pub trait MeshQuery{
|
||||
(self.vert(v1)-self.vert(v0))*((directed_edge_id.parity() as i64)*2-1)
|
||||
}
|
||||
/// This must return a point inside the mesh.
|
||||
#[expect(dead_code)]
|
||||
fn hint_point(&self)->Planar64Vec3;
|
||||
fn vert(&self,vert_id:Self::Vert)->Planar64Vec3;
|
||||
fn face_nd(&self,face_id:Self::Face)->(Self::Normal,Self::Offset);
|
||||
@@ -102,17 +103,21 @@ pub trait MeshQuery{
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct FaceRefs{
|
||||
// I didn't write it down, but I assume the edges are directed
|
||||
// clockwise when looking towards the face normal, i.e. right hand rule.
|
||||
edges:Vec<SubmeshDirectedEdgeId>,
|
||||
//verts are redundant, use edge[i].verts[0]
|
||||
//verts:Vec<VertId>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct EdgeRefs{
|
||||
faces:[SubmeshFaceId;2],//left, right
|
||||
verts:[SubmeshVertId;2],//bottom, top
|
||||
verts:[SubmeshVertId;2],//start, end
|
||||
}
|
||||
#[derive(Debug)]
|
||||
struct VertRefs{
|
||||
faces:Vec<SubmeshFaceId>,
|
||||
// edges are always directed away from the vert
|
||||
edges:Vec<SubmeshDirectedEdgeId>,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
@@ -761,13 +766,13 @@ impl MinkowskiMesh<'_>{
|
||||
infinity_body.velocity=dir;
|
||||
infinity_body.acceleration=vec3::zero();
|
||||
//crawl in from negative infinity along a tangent line to get the closest fev
|
||||
infinity_fev.crawl(self,&infinity_body,Bound::Unbounded,start_time).miss()
|
||||
infinity_fev.crawl::<false>(self,&infinity_body,Bound::Unbounded,start_time).miss()
|
||||
})
|
||||
}
|
||||
pub fn predict_collision_in(&self,relative_body:&Body,range:impl RangeBounds<Time>)->Option<(MinkowskiFace,GigaTime)>{
|
||||
self.closest_fev_not_inside(*relative_body,range.start_bound()).and_then(|fev|{
|
||||
//continue forwards along the body parabola
|
||||
fev.crawl(self,relative_body,range.start_bound(),range.end_bound()).hit()
|
||||
fev.crawl::<true>(self,relative_body,range.start_bound(),range.end_bound()).hit()
|
||||
})
|
||||
}
|
||||
pub fn predict_collision_out(&self,relative_body:&Body,range:impl RangeBounds<Time>)->Option<(MinkowskiFace,GigaTime)>{
|
||||
@@ -777,7 +782,7 @@ impl MinkowskiMesh<'_>{
|
||||
let infinity_body=-relative_body;
|
||||
self.closest_fev_not_inside(infinity_body,lower_bound.as_ref()).and_then(|fev|{
|
||||
//continue backwards along the body parabola
|
||||
fev.crawl(self,&infinity_body,lower_bound.as_ref(),upper_bound.as_ref()).hit()
|
||||
fev.crawl::<true>(self,&infinity_body,lower_bound.as_ref(),upper_bound.as_ref()).hit()
|
||||
//no need to test -time<time_limit because of the first step
|
||||
.map(|(face,time)|(face,-time))
|
||||
})
|
||||
@@ -813,7 +818,7 @@ impl MinkowskiMesh<'_>{
|
||||
fn infinity_in(&self,infinity_body:Body)->Option<(MinkowskiFace,GigaTime)>{
|
||||
let infinity_fev=self.infinity_fev(-infinity_body.velocity,infinity_body.position);
|
||||
// Bound::Included means that the surface of the mesh is included in the mesh
|
||||
infinity_fev.crawl(self,&infinity_body,Bound::Unbounded,Bound::Included(&infinity_body.time)).hit()
|
||||
infinity_fev.crawl::<false>(self,&infinity_body,Bound::Unbounded,Bound::Included(&infinity_body.time)).hit()
|
||||
}
|
||||
pub fn is_point_in_mesh(&self,point:Planar64Vec3)->bool{
|
||||
let infinity_body=Body::new(point,vec3::Y,vec3::zero(),Time::ZERO);
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
// PhysicsMesh
|
||||
// TransformedMesh?
|
||||
@@ -366,7 +366,7 @@ impl_additive_operator!( Fixed, BitXor, bitxor, Self );
|
||||
// non-wide operators. The result is the same width as the inputs.
|
||||
|
||||
// This macro is not used in the default configuration.
|
||||
#[allow(unused_macros)]
|
||||
#[expect(unused_macros)]
|
||||
macro_rules! impl_multiplicative_operator_not_const_generic {
|
||||
( ($struct: ident, $trait: ident, $method: ident, $output: ty ), $width:expr ) => {
|
||||
impl<const F:usize> core::ops::$trait for $struct<$width,F>{
|
||||
@@ -545,7 +545,7 @@ impl_shift_operator!( Fixed, Shr, shr, Self );
|
||||
|
||||
// wide operators. The result width is the sum of the input widths, i.e. none of the multiplication
|
||||
|
||||
#[allow(unused_macros)]
|
||||
#[expect(unused_macros)]
|
||||
macro_rules! impl_wide_operators{
|
||||
($lhs:expr,$rhs:expr)=>{
|
||||
impl core::ops::Mul<Fixed<$rhs,{$rhs*32}>> for Fixed<$lhs,{$lhs*32}>{
|
||||
|
||||
Reference in New Issue
Block a user