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
6 changed files with 56 additions and 47 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

@@ -868,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.
@@ -882,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{},
@@ -1195,6 +1197,11 @@ fn next_instruction_internal(state:&PhysicsState,data:&PhysicsData,time_limit:Ti
let trajectory=state.body.with_acceleration(state.acceleration(data));
//check for collision ends
state.touching.predict_collision_end(&mut collector,&data.models,&data.hitbox_mesh,&trajectory,state.time);
if state.no_clip{
return collector.take();
}
//check for collision starts
let mut aabb=aabb::Aabb::default();
trajectory.grow_aabb(&mut aabb,state.time,collector.time());
@@ -1890,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