diff --git a/engine/physics/src/face_crawler.rs b/engine/physics/src/face_crawler.rs index b444cb8..b0df763 100644 --- a/engine/physics/src/face_crawler.rs +++ b/engine/physics/src/face_crawler.rs @@ -57,13 +57,13 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M> } } //test each edge collision time, ignoring roots with zero or conflicting derivative - for &directed_edge_id in mesh.face_edges(face_id).iter(){ + for &directed_edge_id in mesh.face_edges(face_id).as_ref(){ let edge_n=mesh.directed_edge_n(directed_edge_id); let n=n.cross(edge_n); - let verts=mesh.edge_verts(directed_edge_id.as_undirected()); + let &[v0,v1]=mesh.edge_verts(directed_edge_id.as_undirected()).as_ref(); //WARNING: d is moved out of the *2 block because of adding two vertices! //WARNING: precision is swept under the rug! - for dt in Fixed::<4,128>::zeroes2(n.dot(body.position*2-(mesh.vert(verts[0])+mesh.vert(verts[1]))).fix_4(),n.dot(body.velocity).fix_4()*2,n.dot(body.acceleration).fix_4()){ + for dt in Fixed::<4,128>::zeroes2(n.dot(body.position*2-(mesh.vert(v0)+mesh.vert(v1))).fix_4(),n.dot(body.velocity).fix_4()*2,n.dot(body.acceleration).fix_4()){ if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ best_time=dt; best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt); @@ -77,8 +77,9 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M> //test each face collision time, ignoring roots with zero or conflicting derivative let edge_n=mesh.edge_n(edge_id); let edge_verts=mesh.edge_verts(edge_id); - let delta_pos=body.position*2-(mesh.vert(edge_verts[0])+mesh.vert(edge_verts[1])); - for (i,&edge_face_id) in mesh.edge_faces(edge_id).iter().enumerate(){ + let &[ev0,ev1]=edge_verts.as_ref(); + let delta_pos=body.position*2-(mesh.vert(ev0)+mesh.vert(ev1)); + for (i,&edge_face_id) in mesh.edge_faces(edge_id).as_ref().iter().enumerate(){ let face_n=mesh.face_nd(edge_face_id).0; //edge_n gets parity from the order of edge_faces let n=face_n.cross(edge_n)*((i as i64)*2-1); @@ -92,7 +93,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M> } } //test each vertex collision time, ignoring roots with zero or conflicting derivative - for (i,&vert_id) in edge_verts.iter().enumerate(){ + for (i,&vert_id) in edge_verts.as_ref().iter().enumerate(){ //vertex normal gets parity from vert index let n=edge_n*(1-2*(i as i64)); 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)){ @@ -108,7 +109,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M> }, &FEV::Vert(vert_id)=>{ //test each edge collision time, ignoring roots with zero or conflicting derivative - for &directed_edge_id in mesh.vert_edges(vert_id).iter(){ + for &directed_edge_id in mesh.vert_edges(vert_id).as_ref(){ //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(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){ diff --git a/engine/physics/src/model.rs b/engine/physics/src/model.rs index 57d950a..0269a85 100644 --- a/engine/physics/src/model.rs +++ b/engine/physics/src/model.rs @@ -1,4 +1,3 @@ -use std::borrow::{Borrow,Cow}; use std::collections::{HashSet,HashMap}; use core::ops::Range; use strafesnet_common::integer::vec3::Vector3; @@ -8,6 +7,13 @@ use strafesnet_common::physics::Time; type Body=crate::body::Body<strafesnet_common::physics::TimeInner>; +struct AsRefHelper<T>(T); +impl<T> AsRef<T> for AsRefHelper<T>{ + fn as_ref(&self)->&T{ + &self.0 + } +} + pub trait UndirectedEdge{ type DirectedEdge:Copy+DirectedEdge; fn as_directed(&self,parity:bool)->Self::DirectedEdge; @@ -69,27 +75,27 @@ struct Face{ } struct Vert(Planar64Vec3); pub trait MeshQuery{ - type Face:Clone; - type Edge:Clone+DirectedEdge; - type Vert:Clone; + type Face:Copy; + type Edge:Copy+DirectedEdge; + type Vert:Copy; // Vertex must be Planar64Vec3 because it represents an actual position type Normal; type Offset; fn edge_n(&self,edge_id:<Self::Edge as DirectedEdge>::UndirectedEdge)->Planar64Vec3{ - let verts=self.edge_verts(edge_id); - self.vert(verts[1].clone())-self.vert(verts[0].clone()) + let &[v0,v1]=self.edge_verts(edge_id).as_ref(); + self.vert(v1)-self.vert(v0) } fn directed_edge_n(&self,directed_edge_id:Self::Edge)->Planar64Vec3{ - let verts=self.edge_verts(directed_edge_id.as_undirected()); - (self.vert(verts[1].clone())-self.vert(verts[0].clone()))*((directed_edge_id.parity() as i64)*2-1) + let &[v0,v1]=self.edge_verts(directed_edge_id.as_undirected()).as_ref(); + (self.vert(v1)-self.vert(v0))*((directed_edge_id.parity() as i64)*2-1) } fn vert(&self,vert_id:Self::Vert)->Planar64Vec3; fn face_nd(&self,face_id:Self::Face)->(Self::Normal,Self::Offset); - fn face_edges(&self,face_id:Self::Face)->Cow<[Self::Edge]>; - fn edge_faces(&self,edge_id:<Self::Edge as DirectedEdge>::UndirectedEdge)->Cow<[Self::Face;2]>; - fn edge_verts(&self,edge_id:<Self::Edge as DirectedEdge>::UndirectedEdge)->Cow<[Self::Vert;2]>; - fn vert_edges(&self,vert_id:Self::Vert)->Cow<[Self::Edge]>; - fn vert_faces(&self,vert_id:Self::Vert)->Cow<[Self::Face]>; + fn face_edges(&self,face_id:Self::Face)->impl AsRef<[Self::Edge]>; + fn edge_faces(&self,edge_id:<Self::Edge as DirectedEdge>::UndirectedEdge)->impl AsRef<[Self::Face;2]>; + fn edge_verts(&self,edge_id:<Self::Edge as DirectedEdge>::UndirectedEdge)->impl AsRef<[Self::Vert;2]>; + fn vert_edges(&self,vert_id:Self::Vert)->impl AsRef<[Self::Edge]>; + fn vert_faces(&self,vert_id:Self::Vert)->impl AsRef<[Self::Face]>; } struct FaceRefs{ edges:Vec<SubmeshDirectedEdgeId>, @@ -435,20 +441,20 @@ impl MeshQuery for PhysicsMeshView<'_>{ let vert_idx=self.topology.verts[vert_id.get() as usize].get() as usize; self.data.verts[vert_idx].0 } - fn face_edges(&self,face_id:SubmeshFaceId)->Cow<[SubmeshDirectedEdgeId]>{ - Cow::Borrowed(&self.topology.face_topology[face_id.get() as usize].edges) + fn face_edges(&self,face_id:SubmeshFaceId)->impl AsRef<[SubmeshDirectedEdgeId]>{ + self.topology.face_topology[face_id.get() as usize].edges.as_slice() } - fn edge_faces(&self,edge_id:SubmeshEdgeId)->Cow<[SubmeshFaceId;2]>{ - Cow::Borrowed(&self.topology.edge_topology[edge_id.get() as usize].faces) + fn edge_faces(&self,edge_id:SubmeshEdgeId)->impl AsRef<[SubmeshFaceId;2]>{ + AsRefHelper(self.topology.edge_topology[edge_id.get() as usize].faces) } - fn edge_verts(&self,edge_id:SubmeshEdgeId)->Cow<[SubmeshVertId;2]>{ - Cow::Borrowed(&self.topology.edge_topology[edge_id.get() as usize].verts) + fn edge_verts(&self,edge_id:SubmeshEdgeId)->impl AsRef<[SubmeshVertId;2]>{ + AsRefHelper(self.topology.edge_topology[edge_id.get() as usize].verts) } - fn vert_edges(&self,vert_id:SubmeshVertId)->Cow<[SubmeshDirectedEdgeId]>{ - Cow::Borrowed(&self.topology.vert_topology[vert_id.get() as usize].edges) + fn vert_edges(&self,vert_id:SubmeshVertId)->impl AsRef<[SubmeshDirectedEdgeId]>{ + self.topology.vert_topology[vert_id.get() as usize].edges.as_slice() } - fn vert_faces(&self,vert_id:SubmeshVertId)->Cow<[SubmeshFaceId]>{ - Cow::Borrowed(&self.topology.vert_topology[vert_id.get() as usize].faces) + fn vert_faces(&self,vert_id:SubmeshVertId)->impl AsRef<[SubmeshFaceId]>{ + self.topology.vert_topology[vert_id.get() as usize].faces.as_slice() } } @@ -516,23 +522,23 @@ impl MeshQuery for TransformedMesh<'_>{ self.transform.vertex.transform_point3(self.view.vert(vert_id)).fix_1() } #[inline] - fn face_edges(&self,face_id:SubmeshFaceId)->Cow<[SubmeshDirectedEdgeId]>{ + fn face_edges(&self,face_id:SubmeshFaceId)->impl AsRef<[SubmeshDirectedEdgeId]>{ self.view.face_edges(face_id) } #[inline] - fn edge_faces(&self,edge_id:SubmeshEdgeId)->Cow<[SubmeshFaceId;2]>{ + fn edge_faces(&self,edge_id:SubmeshEdgeId)->impl AsRef<[SubmeshFaceId;2]>{ self.view.edge_faces(edge_id) } #[inline] - fn edge_verts(&self,edge_id:SubmeshEdgeId)->Cow<[SubmeshVertId;2]>{ + fn edge_verts(&self,edge_id:SubmeshEdgeId)->impl AsRef<[SubmeshVertId;2]>{ self.view.edge_verts(edge_id) } #[inline] - fn vert_edges(&self,vert_id:SubmeshVertId)->Cow<[SubmeshDirectedEdgeId]>{ + fn vert_edges(&self,vert_id:SubmeshVertId)->impl AsRef<[SubmeshDirectedEdgeId]>{ self.view.vert_edges(vert_id) } #[inline] - fn vert_faces(&self,vert_id:SubmeshVertId)->Cow<[SubmeshFaceId]>{ + fn vert_faces(&self,vert_id:SubmeshVertId)->impl AsRef<[SubmeshFaceId]>{ self.view.vert_faces(vert_id) } } @@ -621,12 +627,12 @@ impl MinkowskiMesh<'_>{ } fn next_transition_vert(&self,vert_id:MinkowskiVert,best_distance_squared:&mut Fixed<2,64>,infinity_dir:Planar64Vec3,point:Planar64Vec3)->Transition{ let mut best_transition=Transition::Done; - for &directed_edge_id in self.vert_edges(vert_id).iter(){ + for &directed_edge_id in self.vert_edges(vert_id).as_ref(){ let edge_n=self.directed_edge_n(directed_edge_id); //is boundary uncrossable by a crawl from infinity let edge_verts=self.edge_verts(directed_edge_id.as_undirected()); //select opposite vertex - let test_vert_id=edge_verts[directed_edge_id.parity() as usize]; + let test_vert_id=edge_verts.as_ref()[directed_edge_id.parity() as usize]; //test if it's closer let diff=point-self.vert(test_vert_id); if edge_n.dot(infinity_dir).is_zero(){ @@ -642,7 +648,7 @@ impl MinkowskiMesh<'_>{ fn final_ev(&self,vert_id:MinkowskiVert,best_distance_squared:&mut Fixed<2,64>,infinity_dir:Planar64Vec3,point:Planar64Vec3)->EV{ let mut best_transition=EV::Vert(vert_id); let diff=point-self.vert(vert_id); - for &directed_edge_id in self.vert_edges(vert_id).iter(){ + for &directed_edge_id in self.vert_edges(vert_id).as_ref(){ let edge_n=self.directed_edge_n(directed_edge_id); //is boundary uncrossable by a crawl from infinity //check if time of collision is outside Time::MIN..Time::MAX @@ -689,10 +695,10 @@ impl MinkowskiMesh<'_>{ let edge_n=self.edge_n(edge_id); // point is multiplied by two because vert_sum sums two vertices. let delta_pos=point*2-{ - let &[v0,v1]=self.edge_verts(edge_id).borrow(); + let &[v0,v1]=self.edge_verts(edge_id).as_ref(); self.vert(v0)+self.vert(v1) }; - for (i,&face_id) in self.edge_faces(edge_id).iter().enumerate(){ + for (i,&face_id) in self.edge_faces(edge_id).as_ref().iter().enumerate(){ let face_n=self.face_nd(face_id).0; //edge-face boundary nd, n facing out of the face towards the edge let boundary_n=face_n.cross(edge_n)*(i as i64*2-1); @@ -762,12 +768,12 @@ impl MinkowskiMesh<'_>{ }; let mut best_edge=None; let face_n=self.face_nd(contact_face_id).0; - for &directed_edge_id in self.face_edges(contact_face_id).iter(){ + for &directed_edge_id in self.face_edges(contact_face_id).as_ref(){ let edge_n=self.directed_edge_n(directed_edge_id); //f x e points in let n=face_n.cross(edge_n); - let verts=self.edge_verts(directed_edge_id.as_undirected()); - let d=n.dot(self.vert(verts[0])+self.vert(verts[1])); + let &[v0,v1]=self.edge_verts(directed_edge_id.as_undirected()).as_ref(); + let d=n.dot(self.vert(v0)+self.vert(v1)); //WARNING! d outside of *2 //WARNING: truncated precision for dt in Fixed::<4,128>::zeroes2(((n.dot(relative_body.position))*2-d).fix_4(),n.dot(relative_body.velocity).fix_4()*2,n.dot(relative_body.acceleration).fix_4()){ @@ -811,8 +817,8 @@ impl MeshQuery for MinkowskiMesh<'_>{ MinkowskiFace::EdgeEdge(e0,e1,parity)=>{ let edge0_n=self.mesh0.edge_n(e0); let edge1_n=self.mesh1.edge_n(e1); - let &[e0v0,e0v1]=self.mesh0.edge_verts(e0).borrow(); - let &[e1v0,e1v1]=self.mesh1.edge_verts(e1).borrow(); + let &[e0v0,e0v1]=self.mesh0.edge_verts(e0).as_ref(); + let &[e1v0,e1v1]=self.mesh1.edge_verts(e1).as_ref(); let n=edge0_n.cross(edge1_n); let e0d=n.dot(self.mesh0.vert(e0v0)+self.mesh0.vert(e0v1)); let e1d=n.dot(self.mesh1.vert(e1v0)+self.mesh1.vert(e1v1)); @@ -831,44 +837,44 @@ impl MeshQuery for MinkowskiMesh<'_>{ }, } } - fn face_edges(&self,face_id:MinkowskiFace)->Cow<[MinkowskiDirectedEdge]>{ + fn face_edges(&self,face_id:MinkowskiFace)->impl AsRef<[MinkowskiDirectedEdge]>{ match face_id{ MinkowskiFace::VertFace(v0,f1)=>{ - Cow::Owned(self.mesh1.face_edges(f1).iter().map(|&edge_id1|{ + self.mesh1.face_edges(f1).as_ref().iter().map(|&edge_id1| MinkowskiDirectedEdge::VertEdge(v0,edge_id1.reverse()) - }).collect()) + ).collect() }, MinkowskiFace::EdgeEdge(e0,e1,parity)=>{ - let e0v=self.mesh0.edge_verts(e0); - let e1v=self.mesh1.edge_verts(e1); + let &[e0v0,e0v1]=self.mesh0.edge_verts(e0).as_ref(); + let &[e1v0,e1v1]=self.mesh1.edge_verts(e1).as_ref(); //could sort this if ordered edges are needed //probably just need to reverse this list according to parity - Cow::Owned(vec![ - MinkowskiDirectedEdge::VertEdge(e0v[0],e1.as_directed(parity)), - MinkowskiDirectedEdge::EdgeVert(e0.as_directed(!parity),e1v[0]), - MinkowskiDirectedEdge::VertEdge(e0v[1],e1.as_directed(!parity)), - MinkowskiDirectedEdge::EdgeVert(e0.as_directed(parity),e1v[1]), - ]) + vec![ + MinkowskiDirectedEdge::VertEdge(e0v0,e1.as_directed(parity)), + MinkowskiDirectedEdge::EdgeVert(e0.as_directed(!parity),e1v0), + MinkowskiDirectedEdge::VertEdge(e0v1,e1.as_directed(!parity)), + MinkowskiDirectedEdge::EdgeVert(e0.as_directed(parity),e1v1), + ] }, MinkowskiFace::FaceVert(f0,v1)=>{ - Cow::Owned(self.mesh0.face_edges(f0).iter().map(|&edge_id0|{ + self.mesh0.face_edges(f0).as_ref().iter().map(|&edge_id0| MinkowskiDirectedEdge::EdgeVert(edge_id0,v1) - }).collect()) + ).collect() }, } } - fn edge_faces(&self,edge_id:MinkowskiEdge)->Cow<[MinkowskiFace;2]>{ + fn edge_faces(&self,edge_id:MinkowskiEdge)->impl AsRef<[MinkowskiFace;2]>{ match edge_id{ MinkowskiEdge::VertEdge(v0,e1)=>{ //faces are listed backwards from the minkowski mesh let v0e=self.mesh0.vert_edges(v0); - let &[e1f0,e1f1]=self.mesh1.edge_faces(e1).borrow(); - Cow::Owned([(e1f1,false),(e1f0,true)].map(|(edge_face_id1,face_parity)|{ + let &[e1f0,e1f1]=self.mesh1.edge_faces(e1).as_ref(); + AsRefHelper([(e1f1,false),(e1f0,true)].map(|(edge_face_id1,face_parity)|{ let mut best_edge=None; let mut best_d:Ratio<Fixed<8,256>,Fixed<8,256>>=Ratio::new(Fixed::ZERO,Fixed::ONE); let edge_face1_n=self.mesh1.face_nd(edge_face_id1).0; let edge_face1_nn=edge_face1_n.dot(edge_face1_n); - for &directed_edge_id0 in v0e.iter(){ + for &directed_edge_id0 in v0e.as_ref(){ let edge0_n=self.mesh0.directed_edge_n(directed_edge_id0); //must be behind other face. let d=edge_face1_n.dot(edge0_n); @@ -892,13 +898,13 @@ impl MeshQuery for MinkowskiMesh<'_>{ MinkowskiEdge::EdgeVert(e0,v1)=>{ //tracking index with an external variable because .enumerate() is not available let v1e=self.mesh1.vert_edges(v1); - let &[e0f0,e0f1]=self.mesh0.edge_faces(e0).borrow(); - Cow::Owned([(e0f0,true),(e0f1,false)].map(|(edge_face_id0,face_parity)|{ + let &[e0f0,e0f1]=self.mesh0.edge_faces(e0).as_ref(); + AsRefHelper([(e0f0,true),(e0f1,false)].map(|(edge_face_id0,face_parity)|{ let mut best_edge=None; let mut best_d:Ratio<Fixed<8,256>,Fixed<8,256>>=Ratio::new(Fixed::ZERO,Fixed::ONE); let edge_face0_n=self.mesh0.face_nd(edge_face_id0).0; let edge_face0_nn=edge_face0_n.dot(edge_face0_n); - for &directed_edge_id1 in v1e.iter(){ + for &directed_edge_id1 in v1e.as_ref(){ let edge1_n=self.mesh1.directed_edge_n(directed_edge_id1); let d=edge_face0_n.dot(edge1_n); if d.is_negative(){ @@ -918,31 +924,27 @@ impl MeshQuery for MinkowskiMesh<'_>{ }, } } - fn edge_verts(&self,edge_id:MinkowskiEdge)->Cow<[MinkowskiVert;2]>{ - match edge_id{ - MinkowskiEdge::VertEdge(v0,e1)=>{ - Cow::Owned(self.mesh1.edge_verts(e1).map(|vert_id1|{ - MinkowskiVert::VertVert(v0,vert_id1) - })) - }, - MinkowskiEdge::EdgeVert(e0,v1)=>{ - Cow::Owned(self.mesh0.edge_verts(e0).map(|vert_id0|{ - MinkowskiVert::VertVert(vert_id0,v1) - })) - }, - } + fn edge_verts(&self,edge_id:MinkowskiEdge)->impl AsRef<[MinkowskiVert;2]>{ + AsRefHelper(match edge_id{ + MinkowskiEdge::VertEdge(v0,e1)=>(*self.mesh1.edge_verts(e1).as_ref()).map(|vert_id1| + MinkowskiVert::VertVert(v0,vert_id1) + ), + MinkowskiEdge::EdgeVert(e0,v1)=>(*self.mesh0.edge_verts(e0).as_ref()).map(|vert_id0| + MinkowskiVert::VertVert(vert_id0,v1) + ), + }) } - fn vert_edges(&self,vert_id:MinkowskiVert)->Cow<[MinkowskiDirectedEdge]>{ + fn vert_edges(&self,vert_id:MinkowskiVert)->impl AsRef<[MinkowskiDirectedEdge]>{ match vert_id{ MinkowskiVert::VertVert(v0,v1)=>{ let mut edges=Vec::new(); //detect shared volume when the other mesh is mirrored along a test edge dir let v0f=self.mesh0.vert_faces(v0); let v1f=self.mesh1.vert_faces(v1); - let v0f_n:Vec<_>=v0f.iter().map(|&face_id|self.mesh0.face_nd(face_id).0).collect(); - let v1f_n:Vec<_>=v1f.iter().map(|&face_id|self.mesh1.face_nd(face_id).0).collect(); - let the_len=v0f.len()+v1f.len(); - for &directed_edge_id in self.mesh0.vert_edges(v0).iter(){ + let v0f_n:Vec<_>=v0f.as_ref().iter().map(|&face_id|self.mesh0.face_nd(face_id).0).collect(); + let v1f_n:Vec<_>=v1f.as_ref().iter().map(|&face_id|self.mesh1.face_nd(face_id).0).collect(); + let the_len=v0f.as_ref().len()+v1f.as_ref().len(); + for &directed_edge_id in self.mesh0.vert_edges(v0).as_ref(){ 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 @@ -958,7 +960,7 @@ impl MeshQuery for MinkowskiMesh<'_>{ edges.push(MinkowskiDirectedEdge::EdgeVert(directed_edge_id,v1)); } } - for &directed_edge_id in self.mesh1.vert_edges(v1).iter(){ + for &directed_edge_id in self.mesh1.vert_edges(v1).as_ref(){ let n=self.mesh1.directed_edge_n(directed_edge_id); let nn=n.dot(n); let mut face_normals=Vec::with_capacity(the_len); @@ -970,12 +972,13 @@ impl MeshQuery for MinkowskiMesh<'_>{ edges.push(MinkowskiDirectedEdge::VertEdge(v0,directed_edge_id)); } } - Cow::Owned(edges) + edges }, } } - fn vert_faces(&self,_vert_id:MinkowskiVert)->Cow<[MinkowskiFace]>{ - unimplemented!() + fn vert_faces(&self,_vert_id:MinkowskiVert)->impl AsRef<[MinkowskiFace]>{ + unimplemented!(); + vec![] } }