forked from StrafesNET/strafe-client
megatype-ify
This commit is contained in:
parent
5b38b2ca33
commit
50eeeb003a
@ -17,26 +17,31 @@ pub trait DirectedEdge{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)]
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
pub struct VertId(u32);
|
pub struct MeshVertId(u32);
|
||||||
#[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)]
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
pub struct EdgeId(u32);
|
pub struct MeshFaceId(u32);
|
||||||
/// DirectedEdgeId refers to an EdgeId when undirected.
|
|
||||||
#[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)]
|
|
||||||
pub struct DirectedEdgeId(u32);
|
|
||||||
#[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)]
|
|
||||||
pub struct FaceId(u32);
|
|
||||||
|
|
||||||
impl UndirectedEdge for EdgeId{
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
type DirectedEdge=DirectedEdgeId;
|
pub struct SubmeshVertId(u32);
|
||||||
fn as_directed(&self,parity:bool)->DirectedEdgeId{
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
DirectedEdgeId(self.0|((parity as u32)<<(u32::BITS-1)))
|
pub struct SubmeshEdgeId(u32);
|
||||||
|
/// DirectedEdgeId refers to an EdgeId when undirected.
|
||||||
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct SubmeshDirectedEdgeId(u32);
|
||||||
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct SubmeshFaceId(u32);
|
||||||
|
|
||||||
|
impl UndirectedEdge for SubmeshEdgeId{
|
||||||
|
type DirectedEdge=SubmeshDirectedEdgeId;
|
||||||
|
fn as_directed(&self,parity:bool)->SubmeshDirectedEdgeId{
|
||||||
|
SubmeshDirectedEdgeId(self.0|((parity as u32)<<(u32::BITS-1)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl DirectedEdge for DirectedEdgeId{
|
impl DirectedEdge for SubmeshDirectedEdgeId{
|
||||||
type UndirectedEdge=EdgeId;
|
type UndirectedEdge=SubmeshEdgeId;
|
||||||
fn as_undirected(&self)->EdgeId{
|
fn as_undirected(&self)->SubmeshEdgeId{
|
||||||
EdgeId(self.0&!(1<<(u32::BITS-1)))
|
SubmeshEdgeId(self.0&!(1<<(u32::BITS-1)))
|
||||||
}
|
}
|
||||||
fn parity(&self)->bool{
|
fn parity(&self)->bool{
|
||||||
self.0&(1<<(u32::BITS-1))!=0
|
self.0&(1<<(u32::BITS-1))!=0
|
||||||
@ -74,16 +79,16 @@ pub trait MeshQuery<FACE:Clone,EDGE:Clone+DirectedEdge,VERT:Clone>{
|
|||||||
fn vert_faces(&self,vert_id:VERT)->Cow<Vec<FACE>>;
|
fn vert_faces(&self,vert_id:VERT)->Cow<Vec<FACE>>;
|
||||||
}
|
}
|
||||||
struct FaceRefs{
|
struct FaceRefs{
|
||||||
edges:Vec<DirectedEdgeId>,
|
edges:Vec<SubmeshDirectedEdgeId>,
|
||||||
//verts:Vec<VertId>,
|
//verts:Vec<VertId>,
|
||||||
}
|
}
|
||||||
struct EdgeRefs{
|
struct EdgeRefs{
|
||||||
faces:[FaceId;2],//left, right
|
faces:[SubmeshFaceId;2],//left, right
|
||||||
verts:[VertId;2],//bottom, top
|
verts:[SubmeshVertId;2],//bottom, top
|
||||||
}
|
}
|
||||||
struct VertRefs{
|
struct VertRefs{
|
||||||
faces:Vec<FaceId>,
|
faces:Vec<SubmeshFaceId>,
|
||||||
edges:Vec<DirectedEdgeId>,
|
edges:Vec<SubmeshDirectedEdgeId>,
|
||||||
}
|
}
|
||||||
struct PhysicsMeshData{
|
struct PhysicsMeshData{
|
||||||
//this contains all real and virtual faces used in both the complete mesh and convex submeshes
|
//this contains all real and virtual faces used in both the complete mesh and convex submeshes
|
||||||
@ -91,20 +96,24 @@ struct PhysicsMeshData{
|
|||||||
//all remaining faces are virtual to operate internal logic of the face crawler
|
//all remaining faces are virtual to operate internal logic of the face crawler
|
||||||
//and cannot be part of a physics collision
|
//and cannot be part of a physics collision
|
||||||
//virtual faces are only used in convex submeshes.
|
//virtual faces are only used in convex submeshes.
|
||||||
faces:Vec<Face>,
|
faces:Vec<Face>,//MeshFaceId indexes this list
|
||||||
verts:Vec<Vert>,
|
verts:Vec<Vert>,//MeshVertId indexes this list
|
||||||
}
|
}
|
||||||
struct PhysicsMeshTopology{
|
struct PhysicsMeshTopology{
|
||||||
//mapping of local ids to PhysicsMeshData ids
|
//mapping of local ids to PhysicsMeshData ids
|
||||||
faces:Vec<FaceId>,
|
faces:Vec<MeshFaceId>,//SubmeshFaceId indexes this list
|
||||||
verts:Vec<VertId>,
|
verts:Vec<MeshVertId>,//SubmeshVertId indexes this list
|
||||||
//all ids here are local to this object
|
//all ids here are local to this object
|
||||||
face_topology:Vec<FaceRefs>,
|
face_topology:Vec<FaceRefs>,
|
||||||
edge_topology:Vec<EdgeRefs>,
|
edge_topology:Vec<EdgeRefs>,
|
||||||
vert_topology:Vec<VertRefs>,
|
vert_topology:Vec<VertRefs>,
|
||||||
}
|
}
|
||||||
|
#[derive(id::Id)]
|
||||||
|
pub struct PhysicsMeshId(u32);
|
||||||
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
|
pub struct PhysicsSubmeshId(u32);
|
||||||
pub struct PhysicsMesh{
|
pub struct PhysicsMesh{
|
||||||
mesh_data:PhysicsMeshData,
|
data:PhysicsMeshData,
|
||||||
//index 0 is the complete mesh.
|
//index 0 is the complete mesh.
|
||||||
//index 1-2+ is convex submeshes.
|
//index 1-2+ is convex submeshes.
|
||||||
//Most objects in roblox maps are already convex, so the list length is 1
|
//Most objects in roblox maps are already convex, so the list length is 1
|
||||||
@ -115,7 +124,7 @@ pub struct PhysicsMesh{
|
|||||||
impl PhysicsMesh{
|
impl PhysicsMesh{
|
||||||
pub fn unit_cube()->Self{
|
pub fn unit_cube()->Self{
|
||||||
//go go gadget debug print mesh
|
//go go gadget debug print mesh
|
||||||
let mesh_data=PhysicsMeshData{
|
let data=PhysicsMeshData{
|
||||||
faces:vec![
|
faces:vec![
|
||||||
Face{normal:Planar64Vec3::raw( 4294967296, 0, 0),dot:Planar64::raw(4294967296)},
|
Face{normal:Planar64Vec3::raw( 4294967296, 0, 0),dot:Planar64::raw(4294967296)},
|
||||||
Face{normal:Planar64Vec3::raw( 0, 4294967296, 0),dot:Planar64::raw(4294967296)},
|
Face{normal:Planar64Vec3::raw( 0, 4294967296, 0),dot:Planar64::raw(4294967296)},
|
||||||
@ -136,43 +145,43 @@ impl PhysicsMesh{
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
let mesh_topology=PhysicsMeshTopology{
|
let mesh_topology=PhysicsMeshTopology{
|
||||||
faces:(0..mesh_data.faces.len()).map(FaceId).collect(),
|
faces:(0..data.faces.len() as u32).map(MeshFaceId::new).collect(),
|
||||||
verts:(0..mesh_data.verts.len()).map(VertId).collect(),
|
verts:(0..data.verts.len() as u32).map(MeshVertId::new).collect(),
|
||||||
face_topology:vec![
|
face_topology:vec![
|
||||||
FaceRefs{edges:vec![DirectedEdgeId(9223372036854775808),DirectedEdgeId(9223372036854775809),DirectedEdgeId(9223372036854775810),DirectedEdgeId(3)]},
|
FaceRefs{edges:vec![SubmeshDirectedEdgeId(9223372036854775808),SubmeshDirectedEdgeId(9223372036854775809),SubmeshDirectedEdgeId(9223372036854775810),SubmeshDirectedEdgeId(3)]},
|
||||||
FaceRefs{edges:vec![DirectedEdgeId(9223372036854775812),DirectedEdgeId(9223372036854775813),DirectedEdgeId(6),DirectedEdgeId(1)]},
|
FaceRefs{edges:vec![SubmeshDirectedEdgeId(9223372036854775812),SubmeshDirectedEdgeId(9223372036854775813),SubmeshDirectedEdgeId(6),SubmeshDirectedEdgeId(1)]},
|
||||||
FaceRefs{edges:vec![DirectedEdgeId(7),DirectedEdgeId(2),DirectedEdgeId(9223372036854775814),DirectedEdgeId(9223372036854775816)]},
|
FaceRefs{edges:vec![SubmeshDirectedEdgeId(7),SubmeshDirectedEdgeId(2),SubmeshDirectedEdgeId(9223372036854775814),SubmeshDirectedEdgeId(9223372036854775816)]},
|
||||||
FaceRefs{edges:vec![DirectedEdgeId(8),DirectedEdgeId(5),DirectedEdgeId(9223372036854775817),DirectedEdgeId(10)]},
|
FaceRefs{edges:vec![SubmeshDirectedEdgeId(8),SubmeshDirectedEdgeId(5),SubmeshDirectedEdgeId(9223372036854775817),SubmeshDirectedEdgeId(10)]},
|
||||||
FaceRefs{edges:vec![DirectedEdgeId(9223372036854775815),DirectedEdgeId(9223372036854775818),DirectedEdgeId(11),DirectedEdgeId(9223372036854775811)]},
|
FaceRefs{edges:vec![SubmeshDirectedEdgeId(9223372036854775815),SubmeshDirectedEdgeId(9223372036854775818),SubmeshDirectedEdgeId(11),SubmeshDirectedEdgeId(9223372036854775811)]},
|
||||||
FaceRefs{edges:vec![DirectedEdgeId(4),DirectedEdgeId(0),DirectedEdgeId(9223372036854775819),DirectedEdgeId(9)]}
|
FaceRefs{edges:vec![SubmeshDirectedEdgeId(4),SubmeshDirectedEdgeId(0),SubmeshDirectedEdgeId(9223372036854775819),SubmeshDirectedEdgeId(9)]}
|
||||||
],
|
],
|
||||||
edge_topology:vec![
|
edge_topology:vec![
|
||||||
EdgeRefs{faces:[FaceId(0),FaceId(5)],verts:[VertId(0),VertId(1)]},
|
EdgeRefs{faces:[SubmeshFaceId(0),SubmeshFaceId(5)],verts:[SubmeshVertId(0),SubmeshVertId(1)]},
|
||||||
EdgeRefs{faces:[FaceId(0),FaceId(1)],verts:[VertId(1),VertId(2)]},
|
EdgeRefs{faces:[SubmeshFaceId(0),SubmeshFaceId(1)],verts:[SubmeshVertId(1),SubmeshVertId(2)]},
|
||||||
EdgeRefs{faces:[FaceId(0),FaceId(2)],verts:[VertId(2),VertId(3)]},
|
EdgeRefs{faces:[SubmeshFaceId(0),SubmeshFaceId(2)],verts:[SubmeshVertId(2),SubmeshVertId(3)]},
|
||||||
EdgeRefs{faces:[FaceId(4),FaceId(0)],verts:[VertId(0),VertId(3)]},
|
EdgeRefs{faces:[SubmeshFaceId(4),SubmeshFaceId(0)],verts:[SubmeshVertId(0),SubmeshVertId(3)]},
|
||||||
EdgeRefs{faces:[FaceId(1),FaceId(5)],verts:[VertId(1),VertId(4)]},
|
EdgeRefs{faces:[SubmeshFaceId(1),SubmeshFaceId(5)],verts:[SubmeshVertId(1),SubmeshVertId(4)]},
|
||||||
EdgeRefs{faces:[FaceId(1),FaceId(3)],verts:[VertId(4),VertId(5)]},
|
EdgeRefs{faces:[SubmeshFaceId(1),SubmeshFaceId(3)],verts:[SubmeshVertId(4),SubmeshVertId(5)]},
|
||||||
EdgeRefs{faces:[FaceId(2),FaceId(1)],verts:[VertId(2),VertId(5)]},
|
EdgeRefs{faces:[SubmeshFaceId(2),SubmeshFaceId(1)],verts:[SubmeshVertId(2),SubmeshVertId(5)]},
|
||||||
EdgeRefs{faces:[FaceId(4),FaceId(2)],verts:[VertId(3),VertId(6)]},
|
EdgeRefs{faces:[SubmeshFaceId(4),SubmeshFaceId(2)],verts:[SubmeshVertId(3),SubmeshVertId(6)]},
|
||||||
EdgeRefs{faces:[FaceId(2),FaceId(3)],verts:[VertId(5),VertId(6)]},
|
EdgeRefs{faces:[SubmeshFaceId(2),SubmeshFaceId(3)],verts:[SubmeshVertId(5),SubmeshVertId(6)]},
|
||||||
EdgeRefs{faces:[FaceId(3),FaceId(5)],verts:[VertId(4),VertId(7)]},
|
EdgeRefs{faces:[SubmeshFaceId(3),SubmeshFaceId(5)],verts:[SubmeshVertId(4),SubmeshVertId(7)]},
|
||||||
EdgeRefs{faces:[FaceId(4),FaceId(3)],verts:[VertId(6),VertId(7)]},
|
EdgeRefs{faces:[SubmeshFaceId(4),SubmeshFaceId(3)],verts:[SubmeshVertId(6),SubmeshVertId(7)]},
|
||||||
EdgeRefs{faces:[FaceId(5),FaceId(4)],verts:[VertId(0),VertId(7)]}
|
EdgeRefs{faces:[SubmeshFaceId(5),SubmeshFaceId(4)],verts:[SubmeshVertId(0),SubmeshVertId(7)]}
|
||||||
],
|
],
|
||||||
vert_topology:vec![
|
vert_topology:vec![
|
||||||
VertRefs{faces:vec![FaceId(0),FaceId(4),FaceId(5)],edges:vec![DirectedEdgeId(9223372036854775811),DirectedEdgeId(9223372036854775819),DirectedEdgeId(9223372036854775808)]},
|
VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(4),SubmeshFaceId(5)],edges:vec![SubmeshDirectedEdgeId(9223372036854775811),SubmeshDirectedEdgeId(9223372036854775819),SubmeshDirectedEdgeId(9223372036854775808)]},
|
||||||
VertRefs{faces:vec![FaceId(0),FaceId(5),FaceId(1)],edges:vec![DirectedEdgeId(9223372036854775812),DirectedEdgeId(0),DirectedEdgeId(9223372036854775809)]},
|
VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(5),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(9223372036854775812),SubmeshDirectedEdgeId(0),SubmeshDirectedEdgeId(9223372036854775809)]},
|
||||||
VertRefs{faces:vec![FaceId(0),FaceId(2),FaceId(1)],edges:vec![DirectedEdgeId(1),DirectedEdgeId(9223372036854775810),DirectedEdgeId(9223372036854775814)]},
|
VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(2),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(1),SubmeshDirectedEdgeId(9223372036854775810),SubmeshDirectedEdgeId(9223372036854775814)]},
|
||||||
VertRefs{faces:vec![FaceId(0),FaceId(2),FaceId(4)],edges:vec![DirectedEdgeId(2),DirectedEdgeId(3),DirectedEdgeId(9223372036854775815)]},
|
VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(2),SubmeshFaceId(4)],edges:vec![SubmeshDirectedEdgeId(2),SubmeshDirectedEdgeId(3),SubmeshDirectedEdgeId(9223372036854775815)]},
|
||||||
VertRefs{faces:vec![FaceId(3),FaceId(5),FaceId(1)],edges:vec![DirectedEdgeId(4),DirectedEdgeId(9223372036854775817),DirectedEdgeId(9223372036854775813)]},
|
VertRefs{faces:vec![SubmeshFaceId(3),SubmeshFaceId(5),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(4),SubmeshDirectedEdgeId(9223372036854775817),SubmeshDirectedEdgeId(9223372036854775813)]},
|
||||||
VertRefs{faces:vec![FaceId(2),FaceId(3),FaceId(1)],edges:vec![DirectedEdgeId(5),DirectedEdgeId(6),DirectedEdgeId(9223372036854775816)]},
|
VertRefs{faces:vec![SubmeshFaceId(2),SubmeshFaceId(3),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(5),SubmeshDirectedEdgeId(6),SubmeshDirectedEdgeId(9223372036854775816)]},
|
||||||
VertRefs{faces:vec![FaceId(2),FaceId(3),FaceId(4)],edges:vec![DirectedEdgeId(7),DirectedEdgeId(8),DirectedEdgeId(9223372036854775818)]},
|
VertRefs{faces:vec![SubmeshFaceId(2),SubmeshFaceId(3),SubmeshFaceId(4)],edges:vec![SubmeshDirectedEdgeId(7),SubmeshDirectedEdgeId(8),SubmeshDirectedEdgeId(9223372036854775818)]},
|
||||||
VertRefs{faces:vec![FaceId(4),FaceId(3),FaceId(5)],edges:vec![DirectedEdgeId(10),DirectedEdgeId(11),DirectedEdgeId(9)]}
|
VertRefs{faces:vec![SubmeshFaceId(4),SubmeshFaceId(3),SubmeshFaceId(5)],edges:vec![SubmeshDirectedEdgeId(10),SubmeshDirectedEdgeId(11),SubmeshDirectedEdgeId(9)]}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
Self{
|
Self{
|
||||||
mesh_data,
|
data,
|
||||||
submeshes:vec![mesh_topology],
|
submeshes:vec![mesh_topology],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,12 +189,12 @@ impl PhysicsMesh{
|
|||||||
Self::unit_cube()
|
Self::unit_cube()
|
||||||
}
|
}
|
||||||
pub fn mesh_data(&self)->&PhysicsMeshData{
|
pub fn mesh_data(&self)->&PhysicsMeshData{
|
||||||
&self.mesh_data
|
&self.data
|
||||||
}
|
}
|
||||||
pub fn complete_mesh(&self)->&PhysicsMeshTopology{
|
pub fn complete_mesh(&self)->&PhysicsMeshTopology{
|
||||||
&self.submeshes[0]
|
&self.submeshes[0]
|
||||||
}
|
}
|
||||||
pub fn convex_submeshes(&self)->&[PhysicsMeshTopology]{
|
pub fn submeshes(&self)->&[PhysicsMeshTopology]{
|
||||||
if self.submeshes.len()==1{
|
if self.submeshes.len()==1{
|
||||||
//the complete mesh is already a convex mesh
|
//the complete mesh is already a convex mesh
|
||||||
&self.submeshes[0..0]
|
&self.submeshes[0..0]
|
||||||
@ -193,18 +202,30 @@ impl PhysicsMesh{
|
|||||||
&self.submeshes[1..]
|
&self.submeshes[1..]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn submesh_view(&self,submesh_id:PhysicsSubmeshId)->PhysicsMeshView{
|
||||||
|
PhysicsMeshView{
|
||||||
|
data:&self.data,
|
||||||
|
topology:&self.submeshes()[submesh_id.get() as usize],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn submesh_views(&self)->impl Iterator<Item=PhysicsMeshView>{
|
||||||
|
self.submeshes().iter().map(|topology|PhysicsMeshView{
|
||||||
|
data:&self.data,
|
||||||
|
topology,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//mesh builder code
|
//mesh builder code
|
||||||
#[derive(Default,Clone)]
|
#[derive(Default,Clone)]
|
||||||
struct VertRefGuy{
|
struct VertRefGuy{
|
||||||
edges:std::collections::HashSet<DirectedEdgeId>,
|
edges:std::collections::HashSet<SubmeshDirectedEdgeId>,
|
||||||
faces:std::collections::HashSet<FaceId>,
|
faces:std::collections::HashSet<SubmeshFaceId>,
|
||||||
}
|
}
|
||||||
#[derive(Clone,Hash,Eq,PartialEq)]
|
#[derive(Clone,Hash,Eq,PartialEq)]
|
||||||
struct EdgeRefVerts([VertId;2]);
|
struct EdgeRefVerts([SubmeshVertId;2]);
|
||||||
impl EdgeRefVerts{
|
impl EdgeRefVerts{
|
||||||
fn new(v0:VertId,v1:VertId)->(Self,bool){
|
fn new(v0:SubmeshVertId,v1:SubmeshVertId)->(Self,bool){
|
||||||
(if v0.0<v1.0{
|
(if v0.0<v1.0{
|
||||||
Self([v0,v1])
|
Self([v0,v1])
|
||||||
}else{
|
}else{
|
||||||
@ -212,23 +233,23 @@ impl EdgeRefVerts{
|
|||||||
},v0.0<v1.0)
|
},v0.0<v1.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct EdgeRefFaces([FaceId;2]);
|
struct EdgeRefFaces([SubmeshFaceId;2]);
|
||||||
impl EdgeRefFaces{
|
impl EdgeRefFaces{
|
||||||
fn new()->Self{
|
fn new()->Self{
|
||||||
Self([FaceId(0);2])
|
Self([SubmeshFaceId(0);2])
|
||||||
}
|
}
|
||||||
fn push(&mut self,i:usize,face_id:FaceId){
|
fn push(&mut self,i:usize,face_id:SubmeshFaceId){
|
||||||
self.0[i]=face_id;
|
self.0[i]=face_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
struct FaceRefEdges(Vec<DirectedEdgeId>);
|
struct FaceRefEdges(Vec<SubmeshDirectedEdgeId>);
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct EdgePool{
|
struct EdgePool{
|
||||||
edge_guys:Vec<(EdgeRefVerts,EdgeRefFaces)>,
|
edge_guys:Vec<(EdgeRefVerts,EdgeRefFaces)>,
|
||||||
edge_id_from_guy:std::collections::HashMap<EdgeRefVerts,usize>,
|
edge_id_from_guy:std::collections::HashMap<EdgeRefVerts,usize>,
|
||||||
}
|
}
|
||||||
impl EdgePool{
|
impl EdgePool{
|
||||||
fn push(&mut self,edge_ref_verts:EdgeRefVerts)->(&mut EdgeRefFaces,EdgeId){
|
fn push(&mut self,edge_ref_verts:EdgeRefVerts)->(&mut EdgeRefFaces,SubmeshEdgeId){
|
||||||
let edge_id=if let Some(&edge_id)=self.edge_id_from_guy.get(&edge_ref_verts){
|
let edge_id=if let Some(&edge_id)=self.edge_id_from_guy.get(&edge_ref_verts){
|
||||||
edge_id
|
edge_id
|
||||||
}else{
|
}else{
|
||||||
@ -237,7 +258,7 @@ impl EdgePool{
|
|||||||
self.edge_id_from_guy.insert(edge_ref_verts,edge_id);
|
self.edge_id_from_guy.insert(edge_ref_verts,edge_id);
|
||||||
edge_id
|
edge_id
|
||||||
};
|
};
|
||||||
(&mut unsafe{self.edge_guys.get_unchecked_mut(edge_id)}.1,EdgeId(edge_id))
|
(&mut unsafe{self.edge_guys.get_unchecked_mut(edge_id)}.1,SubmeshEdgeId::new(edge_id as u32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl From<&model::IndexedModel> for PhysicsMesh{
|
impl From<&model::IndexedModel> for PhysicsMesh{
|
||||||
@ -250,7 +271,7 @@ impl From<&model::IndexedModel> for PhysicsMesh{
|
|||||||
let mut faces=Vec::new();
|
let mut faces=Vec::new();
|
||||||
let mut face_ref_guys=Vec::new();
|
let mut face_ref_guys=Vec::new();
|
||||||
for group in &indexed_model.polygon_groups{for poly_vertices in group.polys(){
|
for group in &indexed_model.polygon_groups{for poly_vertices in group.polys(){
|
||||||
let face_id=FaceId(face_i);
|
let face_id=SubmeshFaceId::new(face_i);
|
||||||
//one face per poly
|
//one face per poly
|
||||||
let mut normal=Planar64Vec3::ZERO;
|
let mut normal=Planar64Vec3::ZERO;
|
||||||
let len=poly_vertices.len();
|
let len=poly_vertices.len();
|
||||||
@ -266,7 +287,7 @@ impl From<&model::IndexedModel> for PhysicsMesh{
|
|||||||
(v0.x()-v1.x())*(v0.y()+v1.y()),
|
(v0.x()-v1.x())*(v0.y()+v1.y()),
|
||||||
);
|
);
|
||||||
//get/create edge and push face into it
|
//get/create edge and push face into it
|
||||||
let (edge_ref_verts,is_sorted)=EdgeRefVerts::new(VertId(vert0_id),VertId(vert1_id));
|
let (edge_ref_verts,is_sorted)=EdgeRefVerts::new(SubmeshVertId::new(vert0_id as u32),SubmeshVertId::new(vert1_id as u32));
|
||||||
let (edge_ref_faces,edge_id)=edge_pool.push(edge_ref_verts);
|
let (edge_ref_faces,edge_id)=edge_pool.push(edge_ref_verts);
|
||||||
//polygon vertices as assumed to be listed clockwise
|
//polygon vertices as assumed to be listed clockwise
|
||||||
//populate the edge face on the left or right depending on how the edge vertices got sorted
|
//populate the edge face on the left or right depending on how the edge vertices got sorted
|
||||||
@ -311,108 +332,129 @@ impl From<&model::IndexedModel> for PhysicsMesh{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PhysicsMeshView<'a>{
|
||||||
|
data:&'a PhysicsMeshData,
|
||||||
|
topology:&'a PhysicsMeshTopology,
|
||||||
|
}
|
||||||
impl PhysicsMeshView<'_>{
|
impl PhysicsMeshView<'_>{
|
||||||
pub fn verts<'a>(&'a self)->impl Iterator<Item=Planar64Vec3>+'a{
|
pub fn verts<'a>(&'a self)->impl Iterator<Item=Planar64Vec3>+'a{
|
||||||
self.mesh_data.verts.iter().map(|Vert(pos)|*pos)
|
self.data.verts.iter().map(|Vert(pos)|*pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl MeshQuery<FaceId,DirectedEdgeId,VertId> for PhysicsMesh{
|
impl MeshQuery<SubmeshFaceId,SubmeshDirectedEdgeId,SubmeshVertId> for PhysicsMeshView<'_>{
|
||||||
fn face_nd(&self,face_id:FaceId)->(Planar64Vec3,Planar64){
|
fn face_nd(&self,face_id:SubmeshFaceId)->(Planar64Vec3,Planar64){
|
||||||
(self.faces[face_id.0].normal,self.faces[face_id.0].dot)
|
let face_idx=self.topology.faces[face_id.get() as usize].get() as usize;
|
||||||
|
(self.data.faces[face_idx].normal,self.data.faces[face_idx].dot)
|
||||||
}
|
}
|
||||||
//ideally I never calculate the vertex position, but I have to for the graphical meshes...
|
//ideally I never calculate the vertex position, but I have to for the graphical meshes...
|
||||||
fn vert(&self,vert_id:VertId)->Planar64Vec3{
|
fn vert(&self,vert_id:SubmeshVertId)->Planar64Vec3{
|
||||||
self.verts[vert_id.0].0
|
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:FaceId)->Cow<Vec<DirectedEdgeId>>{
|
fn face_edges(&self,face_id:SubmeshFaceId)->Cow<Vec<SubmeshDirectedEdgeId>>{
|
||||||
Cow::Borrowed(&self.face_topology[face_id.0].edges)
|
Cow::Borrowed(&self.topology.face_topology[face_id.get() as usize].edges)
|
||||||
}
|
}
|
||||||
fn edge_faces(&self,edge_id:EdgeId)->Cow<[FaceId;2]>{
|
fn edge_faces(&self,edge_id:SubmeshEdgeId)->Cow<[SubmeshFaceId;2]>{
|
||||||
Cow::Borrowed(&self.edge_topology[edge_id.0].faces)
|
Cow::Borrowed(&self.topology.edge_topology[edge_id.get() as usize].faces)
|
||||||
}
|
}
|
||||||
fn edge_verts(&self,edge_id:EdgeId)->Cow<[VertId;2]>{
|
fn edge_verts(&self,edge_id:SubmeshEdgeId)->Cow<[SubmeshVertId;2]>{
|
||||||
Cow::Borrowed(&self.edge_topology[edge_id.0].verts)
|
Cow::Borrowed(&self.topology.edge_topology[edge_id.get() as usize].verts)
|
||||||
}
|
}
|
||||||
fn vert_edges(&self,vert_id:VertId)->Cow<Vec<DirectedEdgeId>>{
|
fn vert_edges(&self,vert_id:SubmeshVertId)->Cow<Vec<SubmeshDirectedEdgeId>>{
|
||||||
Cow::Borrowed(&self.vert_topology[vert_id.0].edges)
|
Cow::Borrowed(&self.topology.vert_topology[vert_id.get() as usize].edges)
|
||||||
}
|
}
|
||||||
fn vert_faces(&self,vert_id:VertId)->Cow<Vec<FaceId>>{
|
fn vert_faces(&self,vert_id:SubmeshVertId)->Cow<Vec<SubmeshFaceId>>{
|
||||||
Cow::Borrowed(&self.vert_topology[vert_id.0].faces)
|
Cow::Borrowed(&self.topology.vert_topology[vert_id.get() as usize].faces)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PhysicsMeshView<'a>{
|
pub struct PhysicsMeshTransform<'a>{
|
||||||
mesh_data:&'a PhysicsMeshData,
|
vertex:&'a integer::Planar64Affine3,
|
||||||
topology:&'a PhysicsMeshTopology,
|
normal:&'a integer::Planar64Mat3,
|
||||||
|
det:Planar64,
|
||||||
|
}
|
||||||
|
impl PhysicsMeshTransform<'_>{
|
||||||
|
pub fn new<'a>(
|
||||||
|
vertex:&'a integer::Planar64Affine3,
|
||||||
|
normal:&'a integer::Planar64Mat3,
|
||||||
|
det:Planar64
|
||||||
|
)->PhysicsMeshTransform<'a>{
|
||||||
|
PhysicsMeshTransform{
|
||||||
|
vertex,
|
||||||
|
normal,
|
||||||
|
det,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
struct PhysicsMeshTransform<'a>{
|
|
||||||
transform:&'a integer::Planar64Affine3,
|
|
||||||
normal_transform:&'a integer::Planar64Mat3,
|
|
||||||
transform_det:Planar64,
|
|
||||||
}
|
}
|
||||||
pub struct TransformedMesh<'a>{
|
pub struct TransformedMesh<'a>{
|
||||||
mesh:PhysicsMeshView<'a>,
|
view:PhysicsMeshView<'a>,
|
||||||
transform:PhysicsMeshTransform<'a>,
|
transform:PhysicsMeshTransform<'a>,
|
||||||
}
|
}
|
||||||
impl TransformedMesh<'_>{
|
impl TransformedMesh<'_>{
|
||||||
pub fn new<'a>(
|
pub fn new<'a>(
|
||||||
mesh_data:&'a PhysicsMeshData,
|
mesh_data:&'a PhysicsMeshData,
|
||||||
topology:&'a PhysicsMeshTopology,
|
topology:&'a PhysicsMeshTopology,
|
||||||
transform:&'a integer::Planar64Affine3,
|
vertex:&'a integer::Planar64Affine3,
|
||||||
normal_transform:&'a integer::Planar64Mat3,
|
normal:&'a integer::Planar64Mat3,
|
||||||
transform_det:Planar64,
|
det:Planar64,
|
||||||
)->TransformedMesh<'a>{
|
)->TransformedMesh<'a>{
|
||||||
TransformedMesh{
|
TransformedMesh{
|
||||||
mesh_data,
|
view:PhysicsMeshView{
|
||||||
|
data: mesh_data,
|
||||||
topology,
|
topology,
|
||||||
transform,
|
},
|
||||||
normal_transform,
|
transform:PhysicsMeshTransform{
|
||||||
transform_det,
|
vertex,
|
||||||
|
normal,
|
||||||
|
det,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn farthest_vert(&self,dir:Planar64Vec3)->VertId{
|
}
|
||||||
|
fn farthest_vert(&self,dir:Planar64Vec3)->SubmeshVertId{
|
||||||
let mut best_dot=Planar64::MIN;
|
let mut best_dot=Planar64::MIN;
|
||||||
let mut best_vert=VertId(0);
|
let mut best_vert=SubmeshVertId(0);
|
||||||
for (i,vert) in self.mesh.verts.iter().enumerate(){
|
//this happens to be well-defined. there are no virtual virtices
|
||||||
let p=self.transform.transform_point3(vert.0);
|
for (i,vert_id) in self.view.topology.verts.iter().enumerate(){
|
||||||
|
let vert=self.view.data.verts[vert_id.get() as usize];
|
||||||
|
let p=self.transform.vertex.transform_point3(vert.0);
|
||||||
let d=dir.dot(p);
|
let d=dir.dot(p);
|
||||||
if best_dot<d{
|
if best_dot<d{
|
||||||
best_dot=d;
|
best_dot=d;
|
||||||
best_vert=VertId(i);
|
best_vert=SubmeshVertId::new(i as u32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
best_vert
|
best_vert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl MeshQuery<FaceId,DirectedEdgeId,VertId> for TransformedMesh<'_>{
|
impl MeshQuery<SubmeshFaceId,SubmeshDirectedEdgeId,SubmeshVertId> for TransformedMesh<'_>{
|
||||||
fn face_nd(&self,face_id:FaceId)->(Planar64Vec3,Planar64){
|
fn face_nd(&self,face_id:SubmeshFaceId)->(Planar64Vec3,Planar64){
|
||||||
let (n,d)=self.mesh.face_nd(face_id);
|
let (n,d)=self.view.face_nd(face_id);
|
||||||
let transformed_n=*self.normal_transform*n;
|
let transformed_n=*self.transform.normal*n;
|
||||||
let transformed_d=d+transformed_n.dot(self.transform.translation)/self.transform_det;
|
let transformed_d=d+transformed_n.dot(self.transform.vertex.translation)/self.transform.det;
|
||||||
(transformed_n/self.transform_det,transformed_d)
|
(transformed_n/self.transform.det,transformed_d)
|
||||||
}
|
}
|
||||||
fn vert(&self,vert_id:VertId)->Planar64Vec3{
|
fn vert(&self,vert_id:SubmeshVertId)->Planar64Vec3{
|
||||||
self.transform.transform_point3(self.mesh.vert(vert_id))
|
self.transform.vertex.transform_point3(self.view.vert(vert_id))
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn face_edges(&self,face_id:FaceId)->Cow<Vec<DirectedEdgeId>>{
|
fn face_edges(&self,face_id:SubmeshFaceId)->Cow<Vec<SubmeshDirectedEdgeId>>{
|
||||||
self.mesh.face_edges(face_id)
|
self.view.face_edges(face_id)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn edge_faces(&self,edge_id:EdgeId)->Cow<[FaceId;2]>{
|
fn edge_faces(&self,edge_id:SubmeshEdgeId)->Cow<[SubmeshFaceId;2]>{
|
||||||
self.mesh.edge_faces(edge_id)
|
self.view.edge_faces(edge_id)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn edge_verts(&self,edge_id:EdgeId)->Cow<[VertId;2]>{
|
fn edge_verts(&self,edge_id:SubmeshEdgeId)->Cow<[SubmeshVertId;2]>{
|
||||||
self.mesh.edge_verts(edge_id)
|
self.view.edge_verts(edge_id)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn vert_edges(&self,vert_id:VertId)->Cow<Vec<DirectedEdgeId>>{
|
fn vert_edges(&self,vert_id:SubmeshVertId)->Cow<Vec<SubmeshDirectedEdgeId>>{
|
||||||
self.mesh.vert_edges(vert_id)
|
self.view.vert_edges(vert_id)
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn vert_faces(&self,vert_id:VertId)->Cow<Vec<FaceId>>{
|
fn vert_faces(&self,vert_id:SubmeshVertId)->Cow<Vec<SubmeshFaceId>>{
|
||||||
self.mesh.vert_faces(vert_id)
|
self.view.vert_faces(vert_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,12 +464,12 @@ impl MeshQuery<FaceId,DirectedEdgeId,VertId> for TransformedMesh<'_>{
|
|||||||
//(vertex,face)
|
//(vertex,face)
|
||||||
#[derive(Clone,Copy)]
|
#[derive(Clone,Copy)]
|
||||||
pub enum MinkowskiVert{
|
pub enum MinkowskiVert{
|
||||||
VertVert(VertId,VertId),
|
VertVert(SubmeshVertId,SubmeshVertId),
|
||||||
}
|
}
|
||||||
#[derive(Clone,Copy)]
|
#[derive(Clone,Copy)]
|
||||||
pub enum MinkowskiEdge{
|
pub enum MinkowskiEdge{
|
||||||
VertEdge(VertId,EdgeId),
|
VertEdge(SubmeshVertId,SubmeshEdgeId),
|
||||||
EdgeVert(EdgeId,VertId),
|
EdgeVert(SubmeshEdgeId,SubmeshVertId),
|
||||||
//EdgeEdge when edges are parallel
|
//EdgeEdge when edges are parallel
|
||||||
}
|
}
|
||||||
impl UndirectedEdge for MinkowskiEdge{
|
impl UndirectedEdge for MinkowskiEdge{
|
||||||
@ -441,8 +483,8 @@ impl UndirectedEdge for MinkowskiEdge{
|
|||||||
}
|
}
|
||||||
#[derive(Clone,Copy)]
|
#[derive(Clone,Copy)]
|
||||||
pub enum MinkowskiDirectedEdge{
|
pub enum MinkowskiDirectedEdge{
|
||||||
VertEdge(VertId,DirectedEdgeId),
|
VertEdge(SubmeshVertId,SubmeshDirectedEdgeId),
|
||||||
EdgeVert(DirectedEdgeId,VertId),
|
EdgeVert(SubmeshDirectedEdgeId,SubmeshVertId),
|
||||||
//EdgeEdge when edges are parallel
|
//EdgeEdge when edges are parallel
|
||||||
}
|
}
|
||||||
impl DirectedEdge for MinkowskiDirectedEdge{
|
impl DirectedEdge for MinkowskiDirectedEdge{
|
||||||
@ -462,9 +504,9 @@ impl DirectedEdge for MinkowskiDirectedEdge{
|
|||||||
}
|
}
|
||||||
#[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)]
|
#[derive(Debug,Clone,Copy,Hash,Eq,PartialEq)]
|
||||||
pub enum MinkowskiFace{
|
pub enum MinkowskiFace{
|
||||||
VertFace(VertId,FaceId),
|
VertFace(SubmeshVertId,SubmeshFaceId),
|
||||||
EdgeEdge(EdgeId,EdgeId,bool),
|
EdgeEdge(SubmeshEdgeId,SubmeshEdgeId,bool),
|
||||||
FaceVert(FaceId,VertId),
|
FaceVert(SubmeshFaceId,SubmeshVertId),
|
||||||
//EdgeFace
|
//EdgeFace
|
||||||
//FaceEdge
|
//FaceEdge
|
||||||
//FaceFace
|
//FaceFace
|
||||||
|
168
src/physics.rs
168
src/physics.rs
@ -1,7 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use crate::model_physics::{self,PhysicsMesh,TransformedMesh,MeshQuery};
|
use crate::model_physics::{self,PhysicsMesh,TransformedMesh,MeshQuery,PhysicsMeshId,PhysicsSubmeshId};
|
||||||
use strafesnet_common::bvh;
|
use strafesnet_common::bvh;
|
||||||
use strafesnet_common::map;
|
use strafesnet_common::map;
|
||||||
use strafesnet_common::aabb;
|
use strafesnet_common::aabb;
|
||||||
@ -169,11 +169,10 @@ impl PhysicsModels{
|
|||||||
}
|
}
|
||||||
//TODO: "statically" verify the maps don't refer to any nonexistant data, if they do delete the references.
|
//TODO: "statically" verify the maps don't refer to any nonexistant data, if they do delete the references.
|
||||||
//then I can make these getter functions unchecked.
|
//then I can make these getter functions unchecked.
|
||||||
fn mesh(&self,model_id:PhysicsModelId)->TransformedMesh{
|
fn mesh(&self,convex_mesh_id:ConvexMeshId)->TransformedMesh{
|
||||||
let idx=model_id.get() as usize;
|
let model_idx=convex_mesh_id.model_id.get() as usize;
|
||||||
let convex_mesh_id=self.models[idx].convex_mesh_id;
|
|
||||||
TransformedMesh::new(
|
TransformedMesh::new(
|
||||||
&self.meshes[convex_mesh_id.mesh_id.get() as usize].groups[convex_mesh_id.group_id.get() as usize],
|
&self.meshes[model_idx].submesh_view(convex_mesh_id.submesh_id),
|
||||||
&self.models[idx].transform,
|
&self.models[idx].transform,
|
||||||
&self.models[idx].normal_transform,
|
&self.models[idx].normal_transform,
|
||||||
self.models[idx].transform_det,
|
self.models[idx].transform_det,
|
||||||
@ -285,23 +284,19 @@ struct WorldState{}
|
|||||||
struct HitboxMesh{
|
struct HitboxMesh{
|
||||||
halfsize:Planar64Vec3,
|
halfsize:Planar64Vec3,
|
||||||
mesh:PhysicsMesh,
|
mesh:PhysicsMesh,
|
||||||
transform:integer::Planar64Affine3,
|
transform:PhysicsModelTransform,
|
||||||
normal_transform:Planar64Mat3,
|
|
||||||
transform_det:Planar64,
|
|
||||||
}
|
}
|
||||||
impl HitboxMesh{
|
impl HitboxMesh{
|
||||||
fn new(mesh:PhysicsMesh,transform:integer::Planar64Affine3)->Self{
|
fn new(mesh:PhysicsMesh,vertex_transform:integer::Planar64Affine3)->Self{
|
||||||
//calculate extents
|
//calculate extents
|
||||||
let mut aabb=aabb::Aabb::default();
|
let mut aabb=aabb::Aabb::default();
|
||||||
for vert in mesh.verts(){
|
for vert in mesh.complete_mesh_view().verts(){
|
||||||
aabb.grow(transform.transform_point3(vert));
|
aabb.grow(vertex_transform.transform_point3(vert));
|
||||||
}
|
}
|
||||||
Self{
|
Self{
|
||||||
halfsize:aabb.size()/2,
|
halfsize:aabb.size()/2,
|
||||||
mesh,
|
mesh,
|
||||||
transform,
|
transform:PhysicsModelTransform::new(vertex_transform)
|
||||||
normal_transform:transform.matrix3.inverse_times_det().transpose(),
|
|
||||||
transform_det:transform.matrix3.determinant(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -482,15 +477,11 @@ impl TryFrom<&gameplay_attributes::CollisionAttributes> for PhysicsCollisionAttr
|
|||||||
#[derive(id::Id)]
|
#[derive(id::Id)]
|
||||||
struct PhysicsAttributesId(u32);
|
struct PhysicsAttributesId(u32);
|
||||||
|
|
||||||
//id assigned to deindexed IndexedPhysicsGroup
|
|
||||||
#[derive(id::Id)]
|
|
||||||
struct PhysicsMeshId(u32);
|
|
||||||
#[derive(id::Id)]
|
|
||||||
struct PhysicsGroupId(u32);
|
|
||||||
//unique physics meshes indexed by this
|
//unique physics meshes indexed by this
|
||||||
|
#[derive(Debug,Clone,Copy,Eq,Hash,PartialEq)]
|
||||||
struct ConvexMeshId{
|
struct ConvexMeshId{
|
||||||
model_id:PhysicsModelId,// 1:1 with IndexedModelId
|
model_id:PhysicsModelId,
|
||||||
group_id:PhysicsGroupId,// group in model
|
submesh_id:PhysicsSubmeshId,
|
||||||
}
|
}
|
||||||
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
#[derive(Debug,Clone,Copy,Hash,id::Id,Eq,PartialEq)]
|
||||||
struct PhysicsModelId(u32);
|
struct PhysicsModelId(u32);
|
||||||
@ -504,37 +495,50 @@ impl From<ModelId> for PhysicsModelId{
|
|||||||
Self::new(value.get())
|
Self::new(value.get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub struct PhysicsModelTransform{
|
||||||
|
vertex:integer::Planar64Affine3,
|
||||||
|
normal:integer::Planar64Mat3,
|
||||||
|
det:Planar64,
|
||||||
|
}
|
||||||
|
impl PhysicsModelTransform{
|
||||||
|
pub const fn new(vertex_transform:integer::Planar64Affine3)->Self{
|
||||||
|
Self{
|
||||||
|
normal:vertex_transform.matrix3.inverse_times_det().transpose(),
|
||||||
|
det:vertex_transform.matrix3.determinant(),
|
||||||
|
vertex:vertex_transform,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
pub struct PhysicsModel{
|
pub struct PhysicsModel{
|
||||||
//A model is a thing that has a hitbox. can be represented by a list of TreyMesh-es
|
//A model is a thing that has a hitbox. can be represented by a list of TreyMesh-es
|
||||||
//in this iteration, all it needs is extents.
|
//in this iteration, all it needs is extents.
|
||||||
mesh_id:PhysicsMeshId,
|
mesh_id:PhysicsMeshId,
|
||||||
//put these up on the Model (data normalization)
|
//put these up on the Model (data normalization)
|
||||||
attr_id:PhysicsAttributesId,
|
attr_id:PhysicsAttributesId,
|
||||||
transform:integer::Planar64Affine3,
|
transform:PhysicsModelTransform,
|
||||||
normal_transform:integer::Planar64Mat3,
|
|
||||||
transform_det:Planar64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhysicsModel{
|
impl PhysicsModel{
|
||||||
pub fn new(mesh_id:PhysicsMeshId,attr_id:PhysicsAttributesId,transform:integer::Planar64Affine3)->Self{
|
pub const fn new(mesh_id:PhysicsMeshId,attr_id:PhysicsAttributesId,transform:PhysicsModelTransform)->Self{
|
||||||
Self{
|
Self{
|
||||||
mesh_id,
|
mesh_id,
|
||||||
attr_id,
|
attr_id,
|
||||||
transform,
|
transform,
|
||||||
normal_transform:transform.matrix3.inverse_times_det().transpose(),
|
|
||||||
transform_det:transform.matrix3.determinant(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const fn transform(&self)->&PhysicsModelTransform{
|
||||||
|
&self.transform
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
||||||
struct ContactCollision{
|
struct ContactCollision{
|
||||||
face_id:model_physics::MinkowskiFace,
|
face_id:model_physics::MinkowskiFace,
|
||||||
model_id:PhysicsModelId,//using id to avoid lifetimes
|
convex_mesh_id:ConvexMeshId,
|
||||||
}
|
}
|
||||||
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
||||||
struct IntersectCollision{
|
struct IntersectCollision{
|
||||||
model_id:PhysicsModelId,
|
convex_mesh_id:ConvexMeshId,
|
||||||
}
|
}
|
||||||
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
#[derive(Debug,Clone,Eq,Hash,PartialEq)]
|
||||||
enum Collision{
|
enum Collision{
|
||||||
@ -542,16 +546,16 @@ enum Collision{
|
|||||||
Intersect(IntersectCollision),
|
Intersect(IntersectCollision),
|
||||||
}
|
}
|
||||||
impl Collision{
|
impl Collision{
|
||||||
fn model_id(&self)->PhysicsModelId{
|
fn convex_mesh_id(&self)->ConvexMeshId{
|
||||||
match self{
|
match self{
|
||||||
&Collision::Contact(ContactCollision{model_id,face_id:_})
|
&Collision::Contact(ContactCollision{convex_mesh_id,face_id:_})
|
||||||
|&Collision::Intersect(IntersectCollision{model_id})=>model_id,
|
|&Collision::Intersect(IntersectCollision{convex_mesh_id})=>convex_mesh_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn face_id(&self)->Option<model_physics::MinkowskiFace>{
|
fn face_id(&self)->Option<model_physics::MinkowskiFace>{
|
||||||
match self{
|
match self{
|
||||||
&Collision::Contact(ContactCollision{model_id:_,face_id})=>Some(face_id),
|
&Collision::Contact(ContactCollision{convex_mesh_id:_,face_id})=>Some(face_id),
|
||||||
&Collision::Intersect(IntersectCollision{model_id:_})=>None,
|
&Collision::Intersect(IntersectCollision{convex_mesh_id:_})=>None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -584,7 +588,7 @@ impl TouchingState{
|
|||||||
}
|
}
|
||||||
//add accelerators
|
//add accelerators
|
||||||
for contact in &self.contacts{
|
for contact in &self.contacts{
|
||||||
match models.attr(contact.model_id){
|
match models.attr(contact.convex_mesh_id.model_id){
|
||||||
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
||||||
match &general.accelerator{
|
match &general.accelerator{
|
||||||
Some(accelerator)=>a+=accelerator.acceleration,
|
Some(accelerator)=>a+=accelerator.acceleration,
|
||||||
@ -595,7 +599,7 @@ impl TouchingState{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for intersect in &self.intersects{
|
for intersect in &self.intersects{
|
||||||
match models.attr(intersect.model_id){
|
match models.attr(intersect.convex_mesh_id.model_id){
|
||||||
PhysicsCollisionAttributes::Intersect{intersecting,general}=>{
|
PhysicsCollisionAttributes::Intersect{intersecting,general}=>{
|
||||||
match &general.accelerator{
|
match &general.accelerator{
|
||||||
Some(accelerator)=>a+=accelerator.acceleration,
|
Some(accelerator)=>a+=accelerator.acceleration,
|
||||||
@ -636,7 +640,7 @@ impl TouchingState{
|
|||||||
let mut move_state=MoveState::Air;
|
let mut move_state=MoveState::Air;
|
||||||
let mut a=gravity;
|
let mut a=gravity;
|
||||||
for contact in &self.contacts{
|
for contact in &self.contacts{
|
||||||
match models.attr(contact.model_id){
|
match models.attr(contact.convex_mesh_id.model_id){
|
||||||
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
PhysicsCollisionAttributes::Contact{contacting,general}=>{
|
||||||
let normal=contact_normal(models,hitbox_mesh,contact);
|
let normal=contact_normal(models,hitbox_mesh,contact);
|
||||||
match &contacting.contact_behaviour{
|
match &contacting.contact_behaviour{
|
||||||
@ -674,26 +678,26 @@ impl TouchingState{
|
|||||||
let relative_body=VirtualBody::relative(&Body::default(),body).body(time);
|
let relative_body=VirtualBody::relative(&Body::default(),body).body(time);
|
||||||
for contact in &self.contacts{
|
for contact in &self.contacts{
|
||||||
//detect face slide off
|
//detect face slide off
|
||||||
let model_mesh=models.mesh(contact.model_id);
|
let model_mesh=models.mesh(contact.convex_mesh_id);
|
||||||
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(&model_mesh,hitbox_mesh);
|
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh());
|
||||||
collector.collect(minkowski.predict_collision_face_out(&relative_body,collector.time(),contact.face_id).map(|(face,time)|{
|
collector.collect(minkowski.predict_collision_face_out(&relative_body,collector.time(),contact.face_id).map(|(face,time)|{
|
||||||
TimedInstruction{
|
TimedInstruction{
|
||||||
time,
|
time,
|
||||||
instruction:PhysicsInstruction::CollisionEnd(
|
instruction:PhysicsInstruction::CollisionEnd(
|
||||||
Collision::Contact(ContactCollision{model_id:contact.model_id,face_id:contact.face_id})
|
Collision::Contact(ContactCollision{convex_mesh_id:contact.convex_mesh_id,face_id:contact.face_id})
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
for intersect in &self.intersects{
|
for intersect in &self.intersects{
|
||||||
//detect model collision in reverse
|
//detect model collision in reverse
|
||||||
let model_mesh=models.mesh(intersect.model_id);
|
let model_mesh=models.mesh(intersect.convex_mesh_id);
|
||||||
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(&model_mesh,hitbox_mesh);
|
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh());
|
||||||
collector.collect(minkowski.predict_collision_out(&relative_body,collector.time()).map(|(face,time)|{
|
collector.collect(minkowski.predict_collision_out(&relative_body,collector.time()).map(|(face,time)|{
|
||||||
TimedInstruction{
|
TimedInstruction{
|
||||||
time,
|
time,
|
||||||
instruction:PhysicsInstruction::CollisionEnd(
|
instruction:PhysicsInstruction::CollisionEnd(
|
||||||
Collision::Intersect(IntersectCollision{model_id:intersect.model_id})
|
Collision::Intersect(IntersectCollision{convex_mesh_id:intersect.convex_mesh_id})
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@ -809,7 +813,7 @@ pub struct PhysicsState{
|
|||||||
//random collection of contextual data that doesn't belong in PhysicsState
|
//random collection of contextual data that doesn't belong in PhysicsState
|
||||||
pub struct PhysicsData{
|
pub struct PhysicsData{
|
||||||
//permanent map data
|
//permanent map data
|
||||||
bvh:bvh::BvhNode<PhysicsModelId>,
|
bvh:bvh::BvhNode<ConvexMeshId>,
|
||||||
modes:gameplay_modes::Modes,
|
modes:gameplay_modes::Modes,
|
||||||
//transient map/environment data (open world may load/unload)
|
//transient map/environment data (open world may load/unload)
|
||||||
models:PhysicsModels,
|
models:PhysicsModels,
|
||||||
@ -939,33 +943,47 @@ impl PhysicsContext{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_models(&mut self,map:&map::Map){
|
pub fn generate_models(&mut self,map:map::Map){
|
||||||
let mut starts=Vec::new();
|
let mut starts=Vec::new();
|
||||||
let mut spawns=Vec::new();
|
let mut spawns=Vec::new();
|
||||||
let mut attr_hash=HashMap::new();
|
let mut attr_hash=HashMap::new();
|
||||||
for model in &map.models{
|
for (model_id,model) in map.models{
|
||||||
let mesh_id=self.models.meshes.len();
|
let mesh_id=self.data.models.meshes.len();
|
||||||
let mut make_mesh=false;
|
let mut make_mesh=false;
|
||||||
for model_instance in &model.instances{
|
for model_instance in &model.instances{
|
||||||
if let Ok(physics_attributes)=PhysicsCollisionAttributes::try_from(&model_instance.attributes){
|
if let Ok(physics_attributes)=PhysicsCollisionAttributes::try_from(&model_instance.attributes){
|
||||||
let attr_id=if let Some(&attr_id)=attr_hash.get(&physics_attributes){
|
let attr_id=if let Some(&attr_id)=attr_hash.get(&physics_attributes){
|
||||||
attr_id
|
attr_id
|
||||||
}else{
|
}else{
|
||||||
let attr_id=self.models.push_attr(physics_attributes.clone());
|
let attr_id=self.data.models.push_attr(physics_attributes.clone());
|
||||||
attr_hash.insert(physics_attributes,attr_id);
|
attr_hash.insert(physics_attributes,attr_id);
|
||||||
attr_id
|
attr_id
|
||||||
};
|
};
|
||||||
let model_physics=PhysicsModel::new(mesh_id,attr_id,model_instance.transform);
|
let model_physics=PhysicsModel::new(mesh_id,attr_id,model_instance.transform);
|
||||||
make_mesh=true;
|
make_mesh=true;
|
||||||
self.models.push_model(model_physics);
|
self.data.models.push_model(model_physics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if make_mesh{
|
if make_mesh{
|
||||||
self.models.push_mesh(PhysicsMesh::from(model));
|
self.data.models.push_mesh(PhysicsMesh::from(model));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.bvh=bvh::generate_bvh(self.models.aabb_list(),|i|PhysicsModelId::new(i as u32));
|
let convex_mesh_aabb_list=self.data.models.models.iter()
|
||||||
println!("Physics Objects: {}",self.models.models.len());
|
.enumerate().flat_map(|(model_id,model)|{
|
||||||
|
self.data.models.meshes[model.mesh_id.get() as usize].submesh_views()
|
||||||
|
.enumerate().map(|(submesh_id,view)|{
|
||||||
|
let mut aabb=aabb::Aabb::default();
|
||||||
|
for v in view.verts(){
|
||||||
|
aabb.grow(v)
|
||||||
|
}
|
||||||
|
(ConvexMeshId{
|
||||||
|
model_id:PhysicsModelId::new(model_id as u32),
|
||||||
|
submesh_id:PhysicsSubmeshId::new(submesh_id as u32),
|
||||||
|
},aabb)
|
||||||
|
})
|
||||||
|
}).collect();
|
||||||
|
self.data.bvh=bvh::generate_bvh_node(convex_mesh_aabb_list);
|
||||||
|
println!("Physics Objects: {}",self.data.models.models.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
//tickless gaming
|
//tickless gaming
|
||||||
@ -1020,17 +1038,17 @@ impl PhysicsContext{
|
|||||||
//common body
|
//common body
|
||||||
let relative_body=VirtualBody::relative(&Body::default(),&state.body).body(state.time);
|
let relative_body=VirtualBody::relative(&Body::default(),&state.body).body(state.time);
|
||||||
let hitbox_mesh=data.hitbox_mesh.transformed_mesh();
|
let hitbox_mesh=data.hitbox_mesh.transformed_mesh();
|
||||||
data.bvh.the_tester(&aabb,&mut |id|{
|
data.bvh.the_tester(&aabb,&mut |convex_mesh_id|{
|
||||||
//no checks are needed because of the time limits.
|
//no checks are needed because of the time limits.
|
||||||
let model_mesh=data.models.mesh(id);
|
let model_mesh=data.models.mesh(convex_mesh_id);
|
||||||
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(&model_mesh,&hitbox_mesh);
|
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh);
|
||||||
collector.collect(minkowski.predict_collision_in(&relative_body,collector.time())
|
collector.collect(minkowski.predict_collision_in(&relative_body,collector.time())
|
||||||
//temp (?) code to avoid collision loops
|
//temp (?) code to avoid collision loops
|
||||||
.map_or(None,|(face,time)|if time==state.time{None}else{Some((face,time))})
|
.map_or(None,|(face,time)|if time==state.time{None}else{Some((face,time))})
|
||||||
.map(|(face,time)|{
|
.map(|(face,time)|{
|
||||||
TimedInstruction{time,instruction:PhysicsInstruction::CollisionStart(match data.models.attr(id){
|
TimedInstruction{time,instruction:PhysicsInstruction::CollisionStart(match data.models.attr(convex_mesh_id.model_id){
|
||||||
PhysicsCollisionAttributes::Contact{contacting:_,general:_}=>Collision::Contact(ContactCollision{model_id:id,face_id:face}),
|
PhysicsCollisionAttributes::Contact{contacting:_,general:_}=>Collision::Contact(ContactCollision{convex_mesh_id,face_id:face}),
|
||||||
PhysicsCollisionAttributes::Intersect{intersecting:_,general:_}=>Collision::Intersect(IntersectCollision{model_id:id}),
|
PhysicsCollisionAttributes::Intersect{intersecting:_,general:_}=>Collision::Intersect(IntersectCollision{convex_mesh_id}),
|
||||||
})}
|
})}
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
@ -1053,8 +1071,8 @@ fn jumped_velocity(models:&PhysicsModels,style:&StyleModifiers,hitbox_mesh:&Hitb
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn contact_normal(models:&PhysicsModels,hitbox_mesh:&HitboxMesh,contact:&ContactCollision)->Planar64Vec3{
|
fn contact_normal(models:&PhysicsModels,hitbox_mesh:&HitboxMesh,contact:&ContactCollision)->Planar64Vec3{
|
||||||
let model_mesh=models.mesh(contact.model_id);
|
let model_mesh=models.mesh(contact.convex_mesh_id);
|
||||||
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(&model_mesh,&hitbox_mesh.transformed_mesh());
|
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh());
|
||||||
minkowski.face_nd(contact.face_id).0
|
minkowski.face_nd(contact.face_id).0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1116,15 +1134,15 @@ fn teleport(body:&mut Body,touching:&mut TouchingState,models:&PhysicsModels,sty
|
|||||||
}
|
}
|
||||||
fn teleport_to_spawn(body:&mut Body,touching:&mut TouchingState,style:&StyleModifiers,hitbox_mesh:&HitboxMesh,mode:&gameplay_modes::Mode,models:&PhysicsModels,stage_id:gameplay_modes::StageId)->Option<MoveState>{
|
fn teleport_to_spawn(body:&mut Body,touching:&mut TouchingState,style:&StyleModifiers,hitbox_mesh:&HitboxMesh,mode:&gameplay_modes::Mode,models:&PhysicsModels,stage_id:gameplay_modes::StageId)->Option<MoveState>{
|
||||||
let model=models.model(mode.get_spawn_model_id(stage_id)?.into());
|
let model=models.model(mode.get_spawn_model_id(stage_id)?.into());
|
||||||
let point=model.transform.transform_point3(Planar64Vec3::Y)+Planar64Vec3::Y*(style.hitbox.halfsize.y()+Planar64::ONE/16);
|
let point=model.transform.vertex.transform_point3(Planar64Vec3::Y)+Planar64Vec3::Y*(style.hitbox.halfsize.y()+Planar64::ONE/16);
|
||||||
Some(teleport(body,touching,models,style,hitbox_mesh,point))
|
Some(teleport(body,touching,models,style,hitbox_mesh,point))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&mut ModeState,models:&PhysicsModels,mode:&gameplay_modes::Mode,style:&StyleModifiers,hitbox_mesh:&HitboxMesh,touching:&mut TouchingState,body:&mut Body,model_id:PhysicsModelId)->Option<MoveState>{
|
fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&mut ModeState,models:&PhysicsModels,mode:&gameplay_modes::Mode,style:&StyleModifiers,hitbox_mesh:&HitboxMesh,touching:&mut TouchingState,body:&mut Body,convex_mesh_id:ConvexMeshId)->Option<MoveState>{
|
||||||
//TODO: jump count and checkpoints are always reset on teleport.
|
//TODO: jump count and checkpoints are always reset on teleport.
|
||||||
//Map makers are expected to use tools to prevent
|
//Map makers are expected to use tools to prevent
|
||||||
//multi-boosting on JumpLimit boosters such as spawning into a SetVelocity
|
//multi-boosting on JumpLimit boosters such as spawning into a SetVelocity
|
||||||
if let Some(stage_element)=mode.get_element(model_id.into()){
|
if let Some(stage_element)=mode.get_element(convex_mesh_id.model_id.into()){
|
||||||
let stage=mode.get_stage(stage_element.stage_id)?;
|
let stage=mode.get_stage(stage_element.stage_id)?;
|
||||||
if stage_element.force||game.stage_id<stage_element.stage_id{
|
if stage_element.force||game.stage_id<stage_element.stage_id{
|
||||||
//TODO: check if all checkpoints are complete up to destination stage id, otherwise set to checkpoint completion stage it
|
//TODO: check if all checkpoints are complete up to destination stage id, otherwise set to checkpoint completion stage it
|
||||||
@ -1151,23 +1169,23 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
if let Some(next_checkpoint)=stage.ordered_checkpoints.get(&game.next_ordered_checkpoint_id){
|
if let Some(next_checkpoint)=stage.ordered_checkpoints.get(&game.next_ordered_checkpoint_id){
|
||||||
if model_id==next_checkpoint{
|
if convex_mesh_id==next_checkpoint{
|
||||||
//if you hit the next number in a sequence of ordered checkpoints
|
//if you hit the next number in a sequence of ordered checkpoints
|
||||||
//increment the current checkpoint id
|
//increment the current checkpoint id
|
||||||
game.next_ordered_checkpoint_id=gameplay_modes::CheckpointId::new(game.next_ordered_checkpoint_id.get()+1);
|
game.next_ordered_checkpoint_id=gameplay_modes::CheckpointId::new(game.next_ordered_checkpoint_id.get()+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if stage.unordered_checkpoints.contains(model_id.into()){
|
if stage.unordered_checkpoints.contains(convex_mesh_id.model_id.into()){
|
||||||
//count model id in accumulated unordered checkpoints
|
//count model id in accumulated unordered checkpoints
|
||||||
game.unordered_checkpoints.insert(model_id.into());
|
game.unordered_checkpoints.insert(convex_mesh_id.model_id.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match wormhole{
|
match wormhole{
|
||||||
&Some(gameplay_attributes::Wormhole{destination_model})=>{
|
&Some(gameplay_attributes::Wormhole{destination_model})=>{
|
||||||
let origin_model=models.model(model_id);
|
let origin_model=models.model(convex_mesh_id.model_id);
|
||||||
let destination_model=models.model(destination_model.into());
|
let destination_model=models.model(destination_model.into());
|
||||||
//ignore the transform for now
|
//ignore the transform for now
|
||||||
Some(teleport(body,touching,models,style,hitbox_mesh,body.position-origin_model.transform.translation+destination_model.transform.translation))
|
Some(teleport(body,touching,models,style,hitbox_mesh,body.position-origin_model.transform.vertex.translation+destination_model.transform.vertex.translation))
|
||||||
}
|
}
|
||||||
None=>None,
|
None=>None,
|
||||||
}
|
}
|
||||||
@ -1192,8 +1210,8 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
|
|||||||
}
|
}
|
||||||
match ins.instruction{
|
match ins.instruction{
|
||||||
PhysicsInstruction::CollisionStart(c)=>{
|
PhysicsInstruction::CollisionStart(c)=>{
|
||||||
let model_id=c.model_id();
|
let convex_mesh_id=c.convex_mesh_id();
|
||||||
match (data.models.attr(model_id),&c){
|
match (data.models.attr(convex_mesh_id.model_id),&c){
|
||||||
(PhysicsCollisionAttributes::Contact{contacting,general},Collision::Contact(contact))=>{
|
(PhysicsCollisionAttributes::Contact{contacting,general},Collision::Contact(contact))=>{
|
||||||
let mut v=state.body.velocity;
|
let mut v=state.body.velocity;
|
||||||
let normal=contact_normal(&data.models,&data.hitbox_mesh,contact);
|
let normal=contact_normal(&data.models,&data.hitbox_mesh,contact);
|
||||||
@ -1232,7 +1250,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
|
|||||||
//check ground
|
//check ground
|
||||||
state.touching.insert(c);
|
state.touching.insert(c);
|
||||||
//I love making functions with 10 arguments to dodge the borrow checker
|
//I love making functions with 10 arguments to dodge the borrow checker
|
||||||
run_teleport_behaviour(&general.wormhole,&mut state.mode_state,&data.models,&data.modes.get_mode(state.mode_state.mode_id).unwrap(),&state.style,&data.hitbox_mesh,&mut state.touching,&mut state.body,model_id);
|
run_teleport_behaviour(&general.wormhole,&mut state.mode_state,&data.models,&data.modes.get_mode(state.mode_state.mode_id).unwrap(),&state.style,&data.hitbox_mesh,&mut state.touching,&mut state.body,convex_mesh_id);
|
||||||
//flatten v
|
//flatten v
|
||||||
state.touching.constrain_velocity(&data.models,&data.hitbox_mesh,&mut v);
|
state.touching.constrain_velocity(&data.models,&data.hitbox_mesh,&mut v);
|
||||||
match &general.booster{
|
match &general.booster{
|
||||||
@ -1276,13 +1294,13 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
|
|||||||
(PhysicsCollisionAttributes::Intersect{intersecting: _,general},Collision::Intersect(intersect))=>{
|
(PhysicsCollisionAttributes::Intersect{intersecting: _,general},Collision::Intersect(intersect))=>{
|
||||||
//I think that setting the velocity to 0 was preventing surface contacts from entering an infinite loop
|
//I think that setting the velocity to 0 was preventing surface contacts from entering an infinite loop
|
||||||
state.touching.insert(c);
|
state.touching.insert(c);
|
||||||
run_teleport_behaviour(&general.wormhole,&mut state.mode_state,&data.models,&data.modes.get_mode(state.mode_state.mode_id).unwrap(),&state.style,&data.hitbox_mesh,&mut state.touching,&mut state.body,model_id);
|
run_teleport_behaviour(&general.wormhole,&mut state.mode_state,&data.models,&data.modes.get_mode(state.mode_state.mode_id).unwrap(),&state.style,&data.hitbox_mesh,&mut state.touching,&mut state.body,convex_mesh_id);
|
||||||
},
|
},
|
||||||
_=>panic!("invalid pair"),
|
_=>panic!("invalid pair"),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
PhysicsInstruction::CollisionEnd(c) => {
|
PhysicsInstruction::CollisionEnd(c) => {
|
||||||
match data.models.attr(c.model_id()){
|
match data.models.attr(c.convex_mesh_id().model_id){
|
||||||
PhysicsCollisionAttributes::Contact{contacting:_,general:_}=>{
|
PhysicsCollisionAttributes::Contact{contacting:_,general:_}=>{
|
||||||
state.touching.remove(&c);//remove contact before calling contact_constrain_acceleration
|
state.touching.remove(&c);//remove contact before calling contact_constrain_acceleration
|
||||||
//check ground
|
//check ground
|
||||||
@ -1365,7 +1383,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,game:&
|
|||||||
let spawn_point={
|
let spawn_point={
|
||||||
let mode=data.modes.get_mode(state.mode_state.mode_id).unwrap();
|
let mode=data.modes.get_mode(state.mode_state.mode_id).unwrap();
|
||||||
let stage=mode.get_stage(gameplay_modes::StageId::FIRST).unwrap();
|
let stage=mode.get_stage(gameplay_modes::StageId::FIRST).unwrap();
|
||||||
data.models.model(stage.spawn().into()).transform.translation
|
data.models.model(stage.spawn().into()).transform.vertex.translation
|
||||||
};
|
};
|
||||||
set_position(&mut state.body,&mut state.touching,spawn_point);
|
set_position(&mut state.body,&mut state.touching,spawn_point);
|
||||||
set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,Planar64Vec3::ZERO);
|
set_velocity(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,Planar64Vec3::ZERO);
|
||||||
@ -1409,7 +1427,7 @@ fn test_collision_rotated(relative_body:Body,expected_collision_time:Option<Time
|
|||||||
let h1=HitboxMesh::roblox();
|
let h1=HitboxMesh::roblox();
|
||||||
let hitbox_mesh=h1.transformed_mesh();
|
let hitbox_mesh=h1.transformed_mesh();
|
||||||
let platform_mesh=h0.transformed_mesh();
|
let platform_mesh=h0.transformed_mesh();
|
||||||
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(&platform_mesh,&hitbox_mesh);
|
let minkowski=model_physics::MinkowskiMesh::minkowski_sum(platform_mesh,hitbox_mesh);
|
||||||
let collision=minkowski.predict_collision_in(&relative_body,Time::MAX);
|
let collision=minkowski.predict_collision_in(&relative_body,Time::MAX);
|
||||||
assert_eq!(collision.map(|tup|tup.1),expected_collision_time,"Incorrect time of collision");
|
assert_eq!(collision.map(|tup|tup.1),expected_collision_time,"Incorrect time of collision");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user