Compare commits

..

3 Commits

Author SHA1 Message Date
5a1fa50d16 it doesn't work in minkowski
because the return type must be the same for all branches
2026-01-30 07:23:38 -08:00
76d04a8566 again 2026-01-30 07:15:59 -08:00
e56e661805 noclip 2026-01-30 07:02:04 -08:00
9 changed files with 55 additions and 66 deletions

View File

@@ -96,7 +96,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>,Position=Planar64V
}
}
//test each edge collision time, ignoring roots with zero or conflicting derivative
mesh.for_each_face_edge(face_id,|directed_edge_id|{
for directed_edge_id in mesh.face_edges(face_id){
let edge_n=mesh.directed_edge_n(directed_edge_id);
let n=n.cross(edge_n);
let &[v0,v1]=mesh.edge_verts(directed_edge_id.as_undirected()).as_ref();
@@ -110,7 +110,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>,Position=Planar64V
break;
}
}
});
}
//if none:
},
&FEV::Edge(edge_id)=>{
@@ -151,7 +151,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>,Position=Planar64V
},
&FEV::Vert(vert_id)=>{
//test each edge collision time, ignoring roots with zero or conflicting derivative
mesh.for_each_vert_edge(vert_id,|directed_edge_id|{
for directed_edge_id in mesh.vert_edges(vert_id){
//edge is directed away from vertex, but we want the dot product to turn out negative
let n=-mesh.directed_edge_n(directed_edge_id);
for dt in Fixed::<2,64>::zeroes2((n.dot(trajectory.position-mesh.vert(vert_id)))*2,n.dot(trajectory.velocity)*2,n.dot(trajectory.acceleration)){
@@ -162,7 +162,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>,Position=Planar64V
break;
}
}
});
}
//if none:
},
}

View File

@@ -26,13 +26,13 @@ pub trait MeshTopology{
type Edge:UndirectedEdge<DirectedEdge=Self::DirectedEdge>;
type DirectedEdge:DirectedEdge<UndirectedEdge=Self::Edge>;
type Vert;
fn for_each_vert_edge(&self,vert_id:Self::Vert,f:impl FnMut(Self::DirectedEdge));
fn for_each_vert_face(&self,vert_id:Self::Vert,f:impl FnMut(Self::Face));
fn vert_edges(&self,vert_id:Self::Vert)->impl Iterator<Item=Self::DirectedEdge>;
fn vert_faces(&self,vert_id:Self::Vert)->impl Iterator<Item=Self::Face>;
fn edge_faces(&self,edge_id:Self::Edge)->impl AsRef<[Self::Face;2]>;
fn edge_verts(&self,edge_id:Self::Edge)->impl AsRef<[Self::Vert;2]>;
#[expect(unused)]
fn for_each_face_vert(&self,face_id:Self::Face,f:impl FnMut(Self::Vert));
fn for_each_face_edge(&self,face_id:Self::Face,f:impl FnMut(Self::DirectedEdge));
// #[expect(unused)]
// fn face_verts(&self,face_id:Self::Face)->impl Iterator<Item=Self::Vert>;
fn face_edges(&self,face_id:Self::Face)->impl Iterator<Item=Self::DirectedEdge>;
}
// Make face_nd d value relative

View File

@@ -623,7 +623,7 @@ impl<M:MeshQuery<Position=Planar64Vec3>,C:Contains> EVFinder<'_,M,C>
{
fn next_transition_vert(&mut self,vert_id:M::Vert,point:Planar64Vec3)->Transition<M::Vert>{
let mut best_transition=Transition::Done;
self.mesh.for_each_vert_edge(vert_id,|directed_edge_id|{
for directed_edge_id in self.mesh.vert_edges(vert_id){
//test if this edge's opposite vertex closer
let edge_verts=self.mesh.edge_verts(directed_edge_id.as_undirected());
//select opposite vertex
@@ -636,14 +636,14 @@ impl<M:MeshQuery<Position=Planar64Vec3>,C:Contains> EVFinder<'_,M,C>
best_transition=Transition::Vert(test_vert_id);
self.best_distance_squared=distance_squared;
}
});
}
best_transition
}
fn final_ev(&mut self,vert_id:M::Vert,point:Planar64Vec3)->EV<M>{
let mut best_transition=EV::Vert(vert_id);
let vert_pos=self.mesh.vert(vert_id);
let diff=point-vert_pos;
self.mesh.for_each_vert_edge(vert_id,|directed_edge_id|{
for directed_edge_id in self.mesh.vert_edges(vert_id){
//test if this edge is closer
let edge_verts=self.mesh.edge_verts(directed_edge_id.as_undirected());
let test_vert_id=edge_verts.as_ref()[directed_edge_id.parity() as usize];
@@ -664,7 +664,7 @@ impl<M:MeshQuery<Position=Planar64Vec3>,C:Contains> EVFinder<'_,M,C>
self.best_distance_squared=distance_squared;
}
}
});
}
best_transition
}
fn crawl_boundaries(&mut self,mut vert_id:M::Vert,point:Planar64Vec3)->EV<M>

View File

@@ -133,7 +133,7 @@ impl MinkowskiMesh<'_>{
let mut best_time=range.end_bound().map(|&t|into_giga_time(t,trajectory.time));
let mut best_edge=None;
let face_n=self.face_nd(contact_face_id).0;
self.for_each_face_edge(contact_face_id,|directed_edge_id|{
for directed_edge_id in self.face_edges(contact_face_id){
let edge_n=self.directed_edge_n(directed_edge_id);
//f x e points in
let n=face_n.cross(edge_n);
@@ -149,7 +149,7 @@ impl MinkowskiMesh<'_>{
break;
}
}
});
}
best_edge
}
pub fn contains_point(&self,point:Planar64Vec3)->bool{
@@ -211,18 +211,18 @@ impl MeshTopology for MinkowskiMesh<'_>{
type Edge=MinkowskiEdge;
type DirectedEdge=MinkowskiDirectedEdge;
type Vert=MinkowskiVert;
fn for_each_vert_edge(&self,vert_id:Self::Vert,mut f:impl FnMut(Self::DirectedEdge)){
fn vert_edges(&self,vert_id:Self::Vert)->impl Iterator<Item=Self::DirectedEdge>{
match vert_id{
MinkowskiVert::VertVert(v0,v1)=>{
//detect shared volume when the other mesh is mirrored along a test edge dir
let v0f={
let mut faces=Vec::new();
self.mesh0.for_each_vert_face(v0,|face|faces.push(face));
self.mesh0.vert_faces(v0,|face|faces.push(face));
faces
};
let v1f={
let mut faces=Vec::new();
self.mesh1.for_each_vert_face(v1,|face|faces.push(face));
self.mesh1.vert_faces(v1,|face|faces.push(face));
faces
};
let v0f_n:Vec<_>=v0f.iter().map(|&face_id|self.mesh0.face_nd(face_id).0).collect();
@@ -230,7 +230,7 @@ impl MeshTopology for MinkowskiMesh<'_>{
// scratch vector
let mut face_normals=Vec::with_capacity(v0f.len()+v1f.len());
face_normals.clone_from(&v0f_n);
self.mesh0.for_each_vert_edge(v0,|directed_edge_id|{
self.mesh0.vert_edges(v0,|directed_edge_id|{
let n=self.mesh0.directed_edge_n(directed_edge_id);
let nn=n.dot(n);
// TODO: there's gotta be a better way to do this
@@ -247,7 +247,7 @@ impl MeshTopology for MinkowskiMesh<'_>{
}
});
face_normals.clone_from(&v1f_n);
self.mesh1.for_each_vert_edge(v1,|directed_edge_id|{
self.mesh1.vert_edges(v1,|directed_edge_id|{
let n=self.mesh1.directed_edge_n(directed_edge_id);
let nn=n.dot(n);
// drop faces beyond v1f_n
@@ -264,7 +264,7 @@ impl MeshTopology for MinkowskiMesh<'_>{
},
}
}
fn for_each_vert_face(&self,_vert_id:Self::Vert,_f:impl FnMut(Self::Face)){
fn vert_faces(&self,_vert_id:Self::Vert)->impl Iterator<Item=Self::Face>{
unimplemented!()
}
fn edge_faces(&self,edge_id:Self::Edge)->impl AsRef<[Self::Face;2]>{
@@ -273,7 +273,7 @@ impl MeshTopology for MinkowskiMesh<'_>{
//faces are listed backwards from the minkowski mesh
let v0e={
let mut edges=Vec::new();
self.mesh0.for_each_vert_edge(v0,|edge|edges.push(edge));
self.mesh0.vert_edges(v0,|edge|edges.push(edge));
edges
};
let &[e1f0,e1f1]=self.mesh1.edge_faces(e1).as_ref();
@@ -307,7 +307,7 @@ impl MeshTopology for MinkowskiMesh<'_>{
//tracking index with an external variable because .enumerate() is not available
let v1e={
let mut edges=Vec::new();
self.mesh1.for_each_vert_edge(v1,|edge|edges.push(edge));
self.mesh1.vert_edges(v1,|edge|edges.push(edge));
edges
};
let &[e0f0,e0f1]=self.mesh0.edge_faces(e0).as_ref();
@@ -346,13 +346,13 @@ impl MeshTopology for MinkowskiMesh<'_>{
),
})
}
fn for_each_face_vert(&self,_face_id:Self::Face,_f:impl FnMut(Self::Vert)){
unimplemented!()
}
fn for_each_face_edge(&self,face_id:Self::Face,mut f:impl FnMut(Self::DirectedEdge)){
// fn face_verts(&self,_face_id:Self::Face)->impl Iterator<Item=Self::Vert>{
// unimplemented!()
// }
fn face_edges(&self,face_id:Self::Face)->impl Iterator<Item=Self::DirectedEdge>{
match face_id{
MinkowskiFace::VertFace(v0,f1)=>{
self.mesh1.for_each_face_edge(f1,|edge_id1|
self.mesh1.face_edges(f1,|edge_id1|
f(MinkowskiDirectedEdge::VertEdge(v0,edge_id1.reverse()))
)
},
@@ -367,7 +367,7 @@ impl MeshTopology for MinkowskiMesh<'_>{
f(MinkowskiDirectedEdge::EdgeVert(e0.as_directed(parity),e1v1));
},
MinkowskiFace::FaceVert(f0,v1)=>{
self.mesh0.for_each_face_edge(f0,|edge_id0|
self.mesh0.face_edges(f0,|edge_id0|
f(MinkowskiDirectedEdge::EdgeVert(edge_id0,v1))
)
},

View File

@@ -438,11 +438,11 @@ impl MeshTopology for PhysicsMeshView<'_>{
type Edge=SubmeshEdgeId;
type DirectedEdge=SubmeshDirectedEdgeId;
type Vert=SubmeshVertId;
fn for_each_vert_edge(&self,vert_id:Self::Vert,f:impl FnMut(Self::DirectedEdge)){
self.topology.vert_topology[vert_id.get() as usize].edges.iter().copied().for_each(f);
fn vert_edges(&self,vert_id:Self::Vert)->impl Iterator<Item=Self::DirectedEdge>{
self.topology.vert_topology[vert_id.get() as usize].edges.iter().copied()
}
fn for_each_vert_face(&self,vert_id:Self::Vert,f:impl FnMut(Self::Face)){
self.topology.vert_topology[vert_id.get() as usize].faces.iter().copied().for_each(f);
fn vert_faces(&self,vert_id:Self::Vert)->impl Iterator<Item=Self::Face>{
self.topology.vert_topology[vert_id.get() as usize].faces.iter().copied()
}
fn edge_faces(&self,edge_id:Self::Edge)->impl AsRef<[Self::Face;2]>{
AsRefHelper(self.topology.edge_topology[edge_id.get() as usize].faces)
@@ -450,11 +450,11 @@ impl MeshTopology for PhysicsMeshView<'_>{
fn edge_verts(&self,edge_id:Self::Edge)->impl AsRef<[Self::Vert;2]>{
AsRefHelper(self.topology.edge_topology[edge_id.get() as usize].verts)
}
fn for_each_face_vert(&self,_face_id:Self::Face,_f:impl FnMut(Self::Vert)){
unimplemented!()
}
fn for_each_face_edge(&self,face_id:Self::Face,f:impl FnMut(Self::DirectedEdge)){
self.topology.face_topology[face_id.get() as usize].edges.iter().copied().for_each(f);
// fn face_verts(&self,_face_id:Self::Face)->impl Iterator<Item=Self::Vert>{
// unimplemented!()
// }
fn face_edges(&self,face_id:Self::Face)->impl Iterator<Item=Self::DirectedEdge>{
self.topology.face_topology[face_id.get() as usize].edges.iter().copied()
}
}
@@ -538,12 +538,12 @@ impl MeshTopology for TransformedMesh<'_>{
type DirectedEdge=SubmeshDirectedEdgeId;
type Vert=SubmeshVertId;
#[inline]
fn for_each_vert_edge(&self,vert_id:Self::Vert,f:impl FnMut(Self::DirectedEdge)){
self.view.for_each_vert_edge(vert_id,f)
fn vert_edges(&self,vert_id:Self::Vert)->impl Iterator<Item=Self::DirectedEdge>{
self.view.vert_edges(vert_id)
}
#[inline]
fn for_each_vert_face(&self,vert_id:Self::Vert,f:impl FnMut(Self::Face)){
self.view.for_each_vert_face(vert_id,f)
fn vert_faces(&self,vert_id:Self::Vert)->impl Iterator<Item=Self::Face>{
self.view.vert_faces(vert_id)
}
#[inline]
fn edge_faces(&self,edge_id:Self::Edge)->impl AsRef<[Self::Face;2]>{
@@ -553,12 +553,13 @@ impl MeshTopology for TransformedMesh<'_>{
fn edge_verts(&self,edge_id:Self::Edge)->impl AsRef<[Self::Vert;2]>{
self.view.edge_verts(edge_id)
}
fn for_each_face_vert(&self,face_id:Self::Face,f:impl FnMut(Self::Vert)){
self.view.for_each_face_vert(face_id,f)
}
// #[inline]
// fn face_verts(&self,face_id:Self::Face)->impl Iterator<Item=Self::Vert>{
// self.view.face_verts(face_id)
// }
#[inline]
fn for_each_face_edge(&self,face_id:Self::Face,f:impl FnMut(Self::DirectedEdge)){
self.view.for_each_face_edge(face_id,f)
fn face_edges(&self,face_id:Self::Face)->impl Iterator<Item=Self::DirectedEdge>{
self.view.face_edges(face_id)
}
}

View File

@@ -57,9 +57,6 @@ impl InputState{
fn replace_mouse(&mut self,mouse:MouseState,next_mouse:MouseState){
(self.next_mouse,self.mouse)=(next_mouse,mouse);
}
fn get_control(&self,control:Controls)->bool{
self.controls.contains(control)
}
fn set_control(&mut self,control:Controls,state:bool){
self.controls.set(control,state)
}
@@ -871,6 +868,7 @@ pub struct PhysicsState{
//gameplay_state
mode_state:ModeState,
move_state:MoveState,
no_clip:bool,
//run is non optional: when you spawn in a run is created
//the run cannot be finished unless you start it by visiting
//a start zone. If you change mode, a new run is created.
@@ -885,6 +883,7 @@ impl Default for PhysicsState{
style:StyleModifiers::default(),
touching:TouchingState::default(),
move_state:MoveState::Air,
no_clip:false,
camera:PhysicsCamera::default(),
input_state:InputState::default(),
_world:WorldState{},
@@ -925,9 +924,6 @@ impl PhysicsState{
pub fn get_finish_time(&self)->Option<run::Time>{
self.run.get_finish_time()
}
fn is_no_clip_enabled(&self)->bool{
self.input_state.get_control(Controls::Sprint)
}
pub fn clear(&mut self){
self.touching.clear();
}
@@ -1202,7 +1198,7 @@ fn next_instruction_internal(state:&PhysicsState,data:&PhysicsData,time_limit:Ti
//check for collision ends
state.touching.predict_collision_end(&mut collector,&data.models,&data.hitbox_mesh,&trajectory,state.time);
if state.is_no_clip_enabled(){
if state.no_clip{
return collector.take();
}
@@ -1873,8 +1869,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
state.input_state.set_next_mouse(m);
},
Instruction::Mouse(MouseInstruction::ReplaceMouse{m0,m1})=>{
state.camera.move_mouse(state.input_state.mouse_delta());
state.camera.move_mouse(m0.pos-state.input_state.next_mouse.pos);
state.camera.move_mouse(m0.pos-state.input_state.mouse.pos);
state.input_state.replace_mouse(m0,m1);
},
Instruction::Misc(MiscInstruction::SetSensitivity(sensitivity))=>state.camera.sensitivity=sensitivity,
@@ -1902,6 +1897,7 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI
},
Instruction::SetControl(SetControlInstruction::SetSprint(s))=>{
state.input_state.set_control(Controls::Sprint,s);
state.no_clip=s;
},
Instruction::Mode(ModeInstruction::Reset)=>{
//totally reset physics state

View File

@@ -138,7 +138,6 @@ impl MouseInterpolator{
match buffer_state{
BufferState::Unbuffered=>(),
BufferState::Initializing(_time,mouse_state)=>{
println!("{timeout_time} Time out Initializing");
// only a single mouse move was sent in 10ms, this is very much an edge case!
self.push_mouse_and_flush_buffer(TimedInstruction{
time:mouse_state.time,
@@ -149,7 +148,6 @@ impl MouseInterpolator{
});
}
BufferState::Buffered(_time,mouse_state)=>{
println!("{timeout_time} Time out Buffered");
// duplicate the currently buffered mouse state but at a later (future, from the physics perspective) time
self.push_mouse_and_flush_buffer(TimedInstruction{
time:mouse_state.time,
@@ -159,7 +157,6 @@ impl MouseInterpolator{
}
}
fn push_unbuffered_input(&mut self,session_time:SessionTime,physics_time:PhysicsTime,ins:UnbufferedInstruction){
println!("helo");
// new input
// if there is zero instruction buffered, it means the mouse is not moving
// case 1: unbuffered
@@ -180,11 +177,9 @@ impl MouseInterpolator{
let next_mouse_state=MouseState{pos,time:physics_time};
match buffer_state{
BufferState::Unbuffered=>{
println!("{session_time} Unbuffered -> Initializing");
((None,None),BufferState::Initializing(session_time,next_mouse_state))
},
BufferState::Initializing(_time,mouse_state)=>{
println!("{session_time} Initializing -> Buffered");
let ins_mouse=TimedInstruction{
time:mouse_state.time,
instruction:MouseInstruction::ReplaceMouse{
@@ -195,7 +190,6 @@ impl MouseInterpolator{
((Some(ins_mouse),None),BufferState::Buffered(session_time,next_mouse_state))
},
BufferState::Buffered(_time,mouse_state)=>{
println!("{session_time} Buffered");
let ins_mouse=TimedInstruction{
time:mouse_state.time,
instruction:MouseInstruction::SetNextMouse(next_mouse_state.clone()),

View File

@@ -221,7 +221,6 @@ impl InstructionConsumer<Instruction<'_>> for Session{
};
}
println!("=== PRE-PROCESS ===");
// process any timeouts that occured since the last instruction
self.process_exhaustive(ins.time);
@@ -423,7 +422,6 @@ impl InstructionConsumer<Instruction<'_>> for Session{
}
};
println!("=== POST-PROCESS ===");
// process all emitted output instructions
self.process_exhaustive(ins.time);
}

View File

@@ -7,7 +7,7 @@ const BNUM_DIGIT_WIDTH:usize=64;
/// N is the number of u64s to use
/// F is the number of fractional bits (always N*32 lol)
pub struct Fixed<const N:usize,const F:usize>{
bits:BInt<{N}>,
pub(crate)bits:BInt<{N}>,
}
impl<const N:usize,const F:usize> Fixed<N,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}>{