compiles!!!

This commit is contained in:
Quaternions 2024-02-08 20:16:59 -08:00
parent fcc52a1215
commit 1540710942
5 changed files with 95 additions and 93 deletions

View File

@ -150,7 +150,7 @@ impl GraphicsState{
pub fn generate_models(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,map:&map::CompleteMap){ pub fn generate_models(&mut self,device:&wgpu::Device,queue:&wgpu::Queue,map:&map::CompleteMap){
//generate texture view per texture //generate texture view per texture
let num_textures=map.textures.len(); let num_textures=map.textures.len();
let texture_views:Vec<wgpu::TextureView>=map.textures.into_iter().enumerate().map(|(texture_id,texture_data)|{ let texture_views:Vec<wgpu::TextureView>=map.textures.iter().enumerate().map(|(texture_id,texture_data)|{
let image=ddsfile::Dds::read(std::io::Cursor::new(texture_data)).unwrap(); let image=ddsfile::Dds::read(std::io::Cursor::new(texture_data)).unwrap();
let (mut width,mut height)=(image.get_width(),image.get_height()); let (mut width,mut height)=(image.get_width(),image.get_height());
@ -214,7 +214,7 @@ impl GraphicsState{
color:GraphicsModelColor4::new(model.color), color:GraphicsModelColor4::new(model.color),
}; };
//get or create owned mesh map //get or create owned mesh map
let mut owned_mesh_map=if let Some(map)=owned_mesh_id_from_mesh_id_render_config_id.get_mut(&model.mesh){ let owned_mesh_map=if let Some(map)=owned_mesh_id_from_mesh_id_render_config_id.get_mut(&model.mesh){
map map
}else{ }else{
let map=HashMap::new(); let map=HashMap::new();
@ -225,41 +225,38 @@ impl GraphicsState{
//check each group, if it's using a new render config then make a new clone of the model //check each group, if it's using a new render config then make a new clone of the model
if let Some(mesh)=map.meshes.get(model.mesh.get() as usize){ if let Some(mesh)=map.meshes.get(model.mesh.get() as usize){
for graphics_group in mesh.graphics_groups.iter(){ for graphics_group in mesh.graphics_groups.iter(){
let render_config=map.render_configs[graphics_group.render.get() as usize]; let render_config=&map.render_configs[graphics_group.render.get() as usize];
if model.color.w==0.0&&render_config.texture.is_none(){ if model.color.w==0.0&&render_config.texture.is_none(){
continue; continue;
} }
//get or create owned mesh //get or create owned mesh
let mut owned_mesh=unique_render_config_models.get_mut( let owned_mesh_id=if let Some(&owned_mesh_id)=owned_mesh_map.get(&graphics_group.render){
if let Some(&owned_mesh_id)=owned_mesh_map.get(&graphics_group.render){ owned_mesh_id
owned_mesh_id }else{
}else{ //create
//create let owned_mesh_id=IndexedGraphicsMeshOwnedRenderConfigId::new(unique_render_config_models.len() as u32);
let owned_mesh_id=IndexedGraphicsMeshOwnedRenderConfigId::new(unique_render_config_models.len() as u32); owned_mesh_map.insert(graphics_group.render,owned_mesh_id);
owned_mesh_map.insert(graphics_group.render,owned_mesh_id); unique_render_config_models.push(IndexedGraphicsMeshOwnedRenderConfig{
//push unique_pos:mesh.unique_pos.iter().map(|&v|*Into::<glam::Vec3>::into(v).as_ref()).collect(),
unique_render_config_models.push(IndexedGraphicsMeshOwnedRenderConfig{ unique_tex:mesh.unique_tex.iter().map(|v|*v.as_ref()).collect(),
unique_pos:mesh.unique_pos.iter().map(|&v|*Into::<glam::Vec3>::into(v).as_ref()).collect(), unique_normal:mesh.unique_normal.iter().map(|&v|*Into::<glam::Vec3>::into(v).as_ref()).collect(),
unique_tex:mesh.unique_tex.iter().map(|v|*v.as_ref()).collect(), unique_color:mesh.unique_color.iter().map(|v|*v.as_ref()).collect(),
unique_normal:mesh.unique_normal.iter().map(|&v|*Into::<glam::Vec3>::into(v).as_ref()).collect(), unique_vertices:mesh.unique_vertices.clone(),
unique_color:mesh.unique_color.iter().map(|v|*v.as_ref()).collect(), render_config:graphics_group.render,
unique_vertices:mesh.unique_vertices.clone(), polys:model::PolygonGroup::PolygonList(model::PolygonList::new(
render_config:graphics_group.render, graphics_group.groups.iter().flat_map(|polygon_group_id|{
polys:model::PolygonGroup::PolygonList(model::PolygonList::new( mesh.polygon_groups[polygon_group_id.get() as usize].polys()
graphics_group.groups.iter().flat_map(|polygon_group_id|{ })
mesh.polygon_groups[polygon_group_id.get() as usize].polys() .map(|vertex_id_slice|
}) vertex_id_slice.iter().copied().collect()
.map(|vertex_id_slice| ).collect()
vertex_id_slice.iter().copied().collect() )),
).collect() instances:Vec::new(),
)), });
instances:Vec::new(), owned_mesh_id
}); };
owned_mesh_id let owned_mesh=unique_render_config_models.get_mut(owned_mesh_id.get() as usize).unwrap();
}.get() as usize owned_mesh.instances.push(instance.clone());
).unwrap();
//this utm_id is going to take a lot of hashing to generate!
owned_mesh.instances.push(instance);
} }
} }
} }
@ -440,7 +437,7 @@ impl GraphicsState{
indices.push(i); indices.push(i);
}else{ }else{
let i=vertices.len(); let i=vertices.len();
let vertex=model.unique_vertices[vertex_index.get() as usize]; let vertex=&model.unique_vertices[vertex_index.get() as usize];
vertices.push(GraphicsVertex{ vertices.push(GraphicsVertex{
pos:model.unique_pos[vertex.pos.get() as usize], pos:model.unique_pos[vertex.pos.get() as usize],
tex:model.unique_tex[vertex.tex.get() as usize], tex:model.unique_tex[vertex.tex.get() as usize],
@ -482,7 +479,7 @@ impl GraphicsState{
contents:bytemuck::cast_slice(&model_uniforms), contents:bytemuck::cast_slice(&model_uniforms),
usage:wgpu::BufferUsages::UNIFORM|wgpu::BufferUsages::COPY_DST, usage:wgpu::BufferUsages::UNIFORM|wgpu::BufferUsages::COPY_DST,
}); });
let render_config=map.render_configs[model.render_config.get() as usize]; let render_config=&map.render_configs[model.render_config.get() as usize];
let texture_view=match render_config.texture{ let texture_view=match render_config.texture{
Some(texture_id)=>&texture_views[texture_id.get() as usize], Some(texture_id)=>&texture_views[texture_id.get() as usize],
None=>&self.temp_squid_texture_view, None=>&self.temp_squid_texture_view,
@ -979,7 +976,7 @@ const MODEL_BUFFER_SIZE:usize=4*4 + 12 + 4;//let size=std::mem::size_of::<ModelI
const MODEL_BUFFER_SIZE_BYTES:usize=MODEL_BUFFER_SIZE*4; const MODEL_BUFFER_SIZE_BYTES:usize=MODEL_BUFFER_SIZE*4;
fn get_instances_buffer_data(instances:&[GraphicsModelOwned])->Vec<f32>{ fn get_instances_buffer_data(instances:&[GraphicsModelOwned])->Vec<f32>{
let mut raw=Vec::with_capacity(MODEL_BUFFER_SIZE*instances.len()); let mut raw=Vec::with_capacity(MODEL_BUFFER_SIZE*instances.len());
for (i,mi) in instances.iter().enumerate(){ for mi in instances{
//model transform //model transform
raw.extend_from_slice(&AsRef::<[f32; 4*4]>::as_ref(&mi.transform)[..]); raw.extend_from_slice(&AsRef::<[f32; 4*4]>::as_ref(&mi.transform)[..]);
//normal transform //normal transform

View File

@ -1,5 +1,5 @@
use bytemuck::{Pod,Zeroable}; use bytemuck::{Pod,Zeroable};
use strafesnet_common::model::{IndexedVertex,PolygonGroup,RenderConfigId,TextureId}; use strafesnet_common::model::{IndexedVertex,PolygonGroup,RenderConfigId};
#[derive(Clone,Copy,Pod,Zeroable)] #[derive(Clone,Copy,Pod,Zeroable)]
#[repr(C)] #[repr(C)]
pub struct GraphicsVertex{ pub struct GraphicsVertex{
@ -8,7 +8,7 @@ pub struct GraphicsVertex{
pub normal:[f32;3], pub normal:[f32;3],
pub color:[f32;4], pub color:[f32;4],
} }
#[derive(id::Id)] #[derive(Clone,Copy,id::Id)]
pub struct IndexedGraphicsMeshOwnedRenderConfigId(u32); pub struct IndexedGraphicsMeshOwnedRenderConfigId(u32);
pub struct IndexedGraphicsMeshOwnedRenderConfig{ pub struct IndexedGraphicsMeshOwnedRenderConfig{
pub unique_pos:Vec<[f32;3]>, pub unique_pos:Vec<[f32;3]>,
@ -30,7 +30,7 @@ pub struct GraphicsMeshOwnedRenderConfig{
pub render_config:RenderConfigId, pub render_config:RenderConfigId,
pub instances:Vec<GraphicsModelOwned>, pub instances:Vec<GraphicsModelOwned>,
} }
#[derive(Clone,PartialEq,id::Id)] #[derive(Clone,Copy,PartialEq,id::Id)]
pub struct GraphicsModelColor4(glam::Vec4); pub struct GraphicsModelColor4(glam::Vec4);
impl std::hash::Hash for GraphicsModelColor4{ impl std::hash::Hash for GraphicsModelColor4{
fn hash<H:std::hash::Hasher>(&self,state:&mut H) { fn hash<H:std::hash::Hasher>(&self,state:&mut H) {

View File

@ -92,7 +92,7 @@ struct VertRefs{
faces:Vec<SubmeshFaceId>, faces:Vec<SubmeshFaceId>,
edges:Vec<SubmeshDirectedEdgeId>, edges:Vec<SubmeshDirectedEdgeId>,
} }
struct PhysicsMeshData{ pub 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
//faces are sorted such that all faces that belong to the complete mesh appear first, and then //faces are sorted such that all faces that belong to the complete mesh appear first, and then
//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
@ -101,7 +101,7 @@ struct PhysicsMeshData{
faces:Vec<Face>,//MeshFaceId indexes this list faces:Vec<Face>,//MeshFaceId indexes this list
verts:Vec<Vert>,//MeshVertId indexes this list verts:Vec<Vert>,//MeshVertId indexes this list
} }
struct PhysicsMeshTopology{ pub struct PhysicsMeshTopology{
//mapping of local ids to PhysicsMeshData ids //mapping of local ids to PhysicsMeshData ids
faces:Vec<MeshFaceId>,//SubmeshFaceId indexes this list faces:Vec<MeshFaceId>,//SubmeshFaceId indexes this list
verts:Vec<MeshVertId>,//SubmeshVertId indexes this list verts:Vec<MeshVertId>,//SubmeshVertId indexes this list
@ -126,11 +126,10 @@ impl From<MeshId> for PhysicsMeshId{
pub struct PhysicsSubmeshId(u32); pub struct PhysicsSubmeshId(u32);
pub struct PhysicsMesh{ pub struct PhysicsMesh{
data:PhysicsMeshData, data:PhysicsMeshData,
//index 0 is the complete mesh. complete_mesh:PhysicsMeshTopology,
//index 1-2+ is convex submeshes. //Most objects in roblox maps are already convex, so the list length is 0
//Most objects in roblox maps are already convex, so the list length is 1 //as soon as the mesh is divided into 2 submeshes, the list length jumps to 2.
//as soon as the mesh is divided into 2 submeshes, the list length jumps to 3. //length 1 is unnecessary since the complete mesh would be a duplicate of the only submesh, but would still function properly
//length 2 is unnecessary since the complete mesh would be a duplicate of the only submesh, but would still function properly
submeshes:Vec<PhysicsMeshTopology>, submeshes:Vec<PhysicsMeshTopology>,
} }
impl PhysicsMesh{ impl PhysicsMesh{
@ -160,12 +159,12 @@ impl PhysicsMesh{
faces:(0..data.faces.len() as u32).map(MeshFaceId::new).collect(), faces:(0..data.faces.len() as u32).map(MeshFaceId::new).collect(),
verts:(0..data.verts.len() as u32).map(MeshVertId::new).collect(), verts:(0..data.verts.len() as u32).map(MeshVertId::new).collect(),
face_topology:vec![ face_topology:vec![
FaceRefs{edges:vec![SubmeshDirectedEdgeId(9223372036854775808),SubmeshDirectedEdgeId(9223372036854775809),SubmeshDirectedEdgeId(9223372036854775810),SubmeshDirectedEdgeId(3)]}, FaceRefs{edges:vec![SubmeshDirectedEdgeId((9223372036854775808u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId((9223372036854775809u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId((9223372036854775810u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId(3)]},
FaceRefs{edges:vec![SubmeshDirectedEdgeId(9223372036854775812),SubmeshDirectedEdgeId(9223372036854775813),SubmeshDirectedEdgeId(6),SubmeshDirectedEdgeId(1)]}, FaceRefs{edges:vec![SubmeshDirectedEdgeId((9223372036854775812u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId((9223372036854775813u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId(6),SubmeshDirectedEdgeId(1)]},
FaceRefs{edges:vec![SubmeshDirectedEdgeId(7),SubmeshDirectedEdgeId(2),SubmeshDirectedEdgeId(9223372036854775814),SubmeshDirectedEdgeId(9223372036854775816)]}, FaceRefs{edges:vec![SubmeshDirectedEdgeId(7),SubmeshDirectedEdgeId(2),SubmeshDirectedEdgeId((9223372036854775814u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId((9223372036854775816u64-(1<<63)+(1<<31)) as u32)]},
FaceRefs{edges:vec![SubmeshDirectedEdgeId(8),SubmeshDirectedEdgeId(5),SubmeshDirectedEdgeId(9223372036854775817),SubmeshDirectedEdgeId(10)]}, FaceRefs{edges:vec![SubmeshDirectedEdgeId(8),SubmeshDirectedEdgeId(5),SubmeshDirectedEdgeId((9223372036854775817u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId(10)]},
FaceRefs{edges:vec![SubmeshDirectedEdgeId(9223372036854775815),SubmeshDirectedEdgeId(9223372036854775818),SubmeshDirectedEdgeId(11),SubmeshDirectedEdgeId(9223372036854775811)]}, FaceRefs{edges:vec![SubmeshDirectedEdgeId((9223372036854775815u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId((9223372036854775818u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId(11),SubmeshDirectedEdgeId((9223372036854775811u64-(1<<63)+(1<<31)) as u32)]},
FaceRefs{edges:vec![SubmeshDirectedEdgeId(4),SubmeshDirectedEdgeId(0),SubmeshDirectedEdgeId(9223372036854775819),SubmeshDirectedEdgeId(9)]} FaceRefs{edges:vec![SubmeshDirectedEdgeId(4),SubmeshDirectedEdgeId(0),SubmeshDirectedEdgeId((9223372036854775819u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId(9)]}
], ],
edge_topology:vec![ edge_topology:vec![
EdgeRefs{faces:[SubmeshFaceId(0),SubmeshFaceId(5)],verts:[SubmeshVertId(0),SubmeshVertId(1)]}, EdgeRefs{faces:[SubmeshFaceId(0),SubmeshFaceId(5)],verts:[SubmeshVertId(0),SubmeshVertId(1)]},
@ -182,19 +181,20 @@ impl PhysicsMesh{
EdgeRefs{faces:[SubmeshFaceId(5),SubmeshFaceId(4)],verts:[SubmeshVertId(0),SubmeshVertId(7)]} EdgeRefs{faces:[SubmeshFaceId(5),SubmeshFaceId(4)],verts:[SubmeshVertId(0),SubmeshVertId(7)]}
], ],
vert_topology:vec![ vert_topology:vec![
VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(4),SubmeshFaceId(5)],edges:vec![SubmeshDirectedEdgeId(9223372036854775811),SubmeshDirectedEdgeId(9223372036854775819),SubmeshDirectedEdgeId(9223372036854775808)]}, VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(4),SubmeshFaceId(5)],edges:vec![SubmeshDirectedEdgeId((9223372036854775811u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId((9223372036854775819u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId((9223372036854775808u64-(1<<63)+(1<<31)) as u32)]},
VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(5),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(9223372036854775812),SubmeshDirectedEdgeId(0),SubmeshDirectedEdgeId(9223372036854775809)]}, VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(5),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId((9223372036854775812u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId(0),SubmeshDirectedEdgeId((9223372036854775809u64-(1<<63)+(1<<31)) as u32)]},
VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(2),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(1),SubmeshDirectedEdgeId(9223372036854775810),SubmeshDirectedEdgeId(9223372036854775814)]}, VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(2),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(1),SubmeshDirectedEdgeId((9223372036854775810u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId((9223372036854775814u64-(1<<63)+(1<<31)) as u32)]},
VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(2),SubmeshFaceId(4)],edges:vec![SubmeshDirectedEdgeId(2),SubmeshDirectedEdgeId(3),SubmeshDirectedEdgeId(9223372036854775815)]}, VertRefs{faces:vec![SubmeshFaceId(0),SubmeshFaceId(2),SubmeshFaceId(4)],edges:vec![SubmeshDirectedEdgeId(2),SubmeshDirectedEdgeId(3),SubmeshDirectedEdgeId((9223372036854775815u64-(1<<63)+(1<<31)) as u32)]},
VertRefs{faces:vec![SubmeshFaceId(3),SubmeshFaceId(5),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(4),SubmeshDirectedEdgeId(9223372036854775817),SubmeshDirectedEdgeId(9223372036854775813)]}, VertRefs{faces:vec![SubmeshFaceId(3),SubmeshFaceId(5),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(4),SubmeshDirectedEdgeId((9223372036854775817u64-(1<<63)+(1<<31)) as u32),SubmeshDirectedEdgeId((9223372036854775813u64-(1<<63)+(1<<31)) as u32)]},
VertRefs{faces:vec![SubmeshFaceId(2),SubmeshFaceId(3),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(5),SubmeshDirectedEdgeId(6),SubmeshDirectedEdgeId(9223372036854775816)]}, VertRefs{faces:vec![SubmeshFaceId(2),SubmeshFaceId(3),SubmeshFaceId(1)],edges:vec![SubmeshDirectedEdgeId(5),SubmeshDirectedEdgeId(6),SubmeshDirectedEdgeId((9223372036854775816u64-(1<<63)+(1<<31)) as u32)]},
VertRefs{faces:vec![SubmeshFaceId(2),SubmeshFaceId(3),SubmeshFaceId(4)],edges:vec![SubmeshDirectedEdgeId(7),SubmeshDirectedEdgeId(8),SubmeshDirectedEdgeId(9223372036854775818)]}, VertRefs{faces:vec![SubmeshFaceId(2),SubmeshFaceId(3),SubmeshFaceId(4)],edges:vec![SubmeshDirectedEdgeId(7),SubmeshDirectedEdgeId(8),SubmeshDirectedEdgeId((9223372036854775818u64-(1<<63)+(1<<31)) as u32)]},
VertRefs{faces:vec![SubmeshFaceId(4),SubmeshFaceId(3),SubmeshFaceId(5)],edges:vec![SubmeshDirectedEdgeId(10),SubmeshDirectedEdgeId(11),SubmeshDirectedEdgeId(9)]} VertRefs{faces:vec![SubmeshFaceId(4),SubmeshFaceId(3),SubmeshFaceId(5)],edges:vec![SubmeshDirectedEdgeId(10),SubmeshDirectedEdgeId(11),SubmeshDirectedEdgeId(9)]}
] ]
}; };
Self{ Self{
data, data,
submeshes:vec![mesh_topology], complete_mesh:mesh_topology,
submeshes:Vec::new(),
} }
} }
pub fn unit_cylinder()->Self{ pub fn unit_cylinder()->Self{
@ -206,7 +206,7 @@ impl PhysicsMesh{
} }
#[inline] #[inline]
pub const fn complete_mesh(&self)->&PhysicsMeshTopology{ pub const fn complete_mesh(&self)->&PhysicsMeshTopology{
&self.submeshes[0] &self.complete_mesh
} }
#[inline] #[inline]
pub const fn complete_mesh_view(&self)->PhysicsMeshView{ pub const fn complete_mesh_view(&self)->PhysicsMeshView{
@ -216,12 +216,16 @@ impl PhysicsMesh{
} }
} }
#[inline] #[inline]
pub const fn submeshes(&self)->&[PhysicsMeshTopology]{ pub fn submeshes(&self)->&[PhysicsMeshTopology]{
//the complete mesh is already a convex mesh when len()==1, len()==2 is invalid but will still work //the complete mesh is already a convex mesh when len()==0, len()==1 is invalid but will still work
&self.submeshes[self.submeshes.len().saturating_sub(1).min(1)..] if self.submeshes.len()==0{
std::slice::from_ref(&self.complete_mesh)
}else{
&self.submeshes.as_slice()
}
} }
#[inline] #[inline]
pub const fn submesh_view(&self,submesh_id:PhysicsSubmeshId)->PhysicsMeshView{ pub fn submesh_view(&self,submesh_id:PhysicsSubmeshId)->PhysicsMeshView{
PhysicsMeshView{ PhysicsMeshView{
data:&self.data, data:&self.data,
topology:&self.submeshes()[submesh_id.get() as usize], topology:&self.submeshes()[submesh_id.get() as usize],
@ -257,7 +261,7 @@ impl EdgeRefFaces{
const fn new()->Self{ const fn new()->Self{
Self([SubmeshFaceId(0);2]) Self([SubmeshFaceId(0);2])
} }
const fn push(&mut self,i:usize,face_id:SubmeshFaceId){ fn push(&mut self,i:usize,face_id:SubmeshFaceId){
self.0[i]=face_id; self.0[i]=face_id;
} }
} }
@ -283,20 +287,21 @@ impl EdgePool{
impl From<&model::Mesh> for PhysicsMesh{ impl From<&model::Mesh> for PhysicsMesh{
fn from(mesh:&model::Mesh)->Self{ fn from(mesh:&model::Mesh)->Self{
assert!(mesh.unique_pos.len()!=0,"Mesh cannot have 0 vertices"); assert!(mesh.unique_pos.len()!=0,"Mesh cannot have 0 vertices");
let verts=mesh.unique_pos.into_iter().map(Vert).collect(); let verts=mesh.unique_pos.iter().copied().map(Vert).collect();
let mut faces=Vec::new(); let mut faces=Vec::new();
let mut face_id_from_face=HashMap::new(); let mut face_id_from_face=HashMap::new();
let submeshes=mesh.physics_groups.iter().enumerate().map(|(submesh_id,physics_group)|{ let mut mesh_topologies:Vec<PhysicsMeshTopology>=mesh.physics_groups.iter().map(|physics_group|{
//construct submesh //construct submesh
let mut submesh_faces=Vec::new();//these contain a map from submeshId->meshId let mut submesh_faces=Vec::new();//these contain a map from submeshId->meshId
let mut submesh_verts=Vec::new(); let mut submesh_verts=Vec::new();
let mut submesh_vert_id_from_mesh_vert_id=HashMap::<MeshVertId,SubmeshVertId>::new(); let mut submesh_vert_id_from_mesh_vert_id=HashMap::<MeshVertId,SubmeshVertId>::new();
//lazy closure //lazy closure
let get_submesh_vert_id=|vert_id:MeshVertId|{ let mut get_submesh_vert_id=|vert_id:MeshVertId|{
if let Some(&submesh_vert_id)=submesh_vert_id_from_mesh_vert_id.get(&vert_id){ if let Some(&submesh_vert_id)=submesh_vert_id_from_mesh_vert_id.get(&vert_id){
submesh_vert_id submesh_vert_id
}else{ }else{
let submesh_vert_id=SubmeshVertId::new(vert_id.get() as u32); let submesh_vert_id=SubmeshVertId::new(submesh_verts.len() as u32);
submesh_verts.push(vert_id);
submesh_vert_id_from_mesh_vert_id.insert(vert_id,submesh_vert_id); submesh_vert_id_from_mesh_vert_id.insert(vert_id,submesh_vert_id);
submesh_vert_id submesh_vert_id
} }
@ -304,9 +309,8 @@ impl From<&model::Mesh> for PhysicsMesh{
let mut edge_pool=EdgePool::default(); let mut edge_pool=EdgePool::default();
let mut vert_ref_guys=vec![VertRefGuy::default();mesh.unique_pos.len()]; let mut vert_ref_guys=vec![VertRefGuy::default();mesh.unique_pos.len()];
let mut face_ref_guys=Vec::new(); let mut face_ref_guys=Vec::new();
let submesh_id=PhysicsSubmeshId::new(submesh_id as u32);
for polygon_group_id in &physics_group.groups{ for polygon_group_id in &physics_group.groups{
let polygon_group=mesh.polygon_groups[polygon_group_id.get() as usize]; let polygon_group=&mesh.polygon_groups[polygon_group_id.get() as usize];
for poly_vertices in polygon_group.polys(){ for poly_vertices in polygon_group.polys(){
let submesh_face_id=SubmeshFaceId::new(submesh_faces.len() as u32); let submesh_face_id=SubmeshFaceId::new(submesh_faces.len() as u32);
//one face per poly //one face per poly
@ -354,7 +358,7 @@ impl From<&model::Mesh> for PhysicsMesh{
Some(&face_id)=>face_id, Some(&face_id)=>face_id,
None=>{ None=>{
let face_id=MeshFaceId::new(faces.len() as u32); let face_id=MeshFaceId::new(faces.len() as u32);
face_id_from_face.insert(face,face_id); face_id_from_face.insert(face.clone(),face_id);
faces.push(face); faces.push(face);
face_id face_id
} }
@ -385,12 +389,13 @@ impl From<&model::Mesh> for PhysicsMesh{
faces, faces,
verts, verts,
}, },
submeshes, complete_mesh:mesh_topologies.pop().unwrap(),
submeshes:mesh_topologies,
} }
} }
} }
struct PhysicsMeshView<'a>{ pub struct PhysicsMeshView<'a>{
data:&'a PhysicsMeshData, data:&'a PhysicsMeshData,
topology:&'a PhysicsMeshTopology, topology:&'a PhysicsMeshTopology,
} }
@ -460,8 +465,7 @@ impl TransformedMesh<'_>{
let mut best_vert=SubmeshVertId(0); let mut best_vert=SubmeshVertId(0);
//this happens to be well-defined. there are no virtual virtices //this happens to be well-defined. there are no virtual virtices
for (i,vert_id) in self.view.topology.verts.iter().enumerate(){ 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(self.view.data.verts[vert_id.get() as usize].0);
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;

View File

@ -170,7 +170,7 @@ 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,convex_mesh_id:ConvexMeshId)->TransformedMesh{ fn mesh(&self,convex_mesh_id:ConvexMeshId)->TransformedMesh{
let model=self.models[&convex_mesh_id.model_id]; let model=&self.models[&convex_mesh_id.model_id];
TransformedMesh::new( TransformedMesh::new(
self.meshes[&model.mesh_id].submesh_view(convex_mesh_id.submesh_id), self.meshes[&model.mesh_id].submesh_view(convex_mesh_id.submesh_id),
&model.transform &model.transform
@ -201,7 +201,7 @@ pub struct PhysicsCamera{
} }
impl PhysicsCamera{ impl PhysicsCamera{
const ANGLE_PITCH_LOWER_LIMIT:Angle32=-Angle32::FRAC_PI_2; const ANGLE_PITCH_LOWER_LIMIT:Angle32=Angle32::NEG_FRAC_PI_2;
const ANGLE_PITCH_UPPER_LIMIT:Angle32=Angle32::FRAC_PI_2; const ANGLE_PITCH_UPPER_LIMIT:Angle32=Angle32::FRAC_PI_2;
pub fn move_mouse(&mut self,mouse_pos:glam::IVec2){ pub fn move_mouse(&mut self,mouse_pos:glam::IVec2){
let mut unclamped_mouse_pos=mouse_pos-self.mouse.pos+self.clamped_mouse_pos; let mut unclamped_mouse_pos=mouse_pos-self.mouse.pos+self.clamped_mouse_pos;
@ -261,13 +261,13 @@ mod gameplay{
pub const fn get_next_ordered_checkpoint_id(&self)->gameplay_modes::CheckpointId{ pub const fn get_next_ordered_checkpoint_id(&self)->gameplay_modes::CheckpointId{
self.next_ordered_checkpoint_id self.next_ordered_checkpoint_id
} }
pub const fn get_jump_count(&self,model_id:ModelId)->Option<u32>{ pub fn get_jump_count(&self,model_id:ModelId)->Option<u32>{
self.jump_counts.get(&model_id).copied() self.jump_counts.get(&model_id).copied()
} }
pub const fn ordered_checkpoint_count(&self)->u32{ pub const fn ordered_checkpoint_count(&self)->u32{
self.next_ordered_checkpoint_id.get() self.next_ordered_checkpoint_id.get()
} }
pub const fn unordered_checkpoint_count(&self)->u32{ pub fn unordered_checkpoint_count(&self)->u32{
self.unordered_checkpoints.len() as u32 self.unordered_checkpoints.len() as u32
} }
pub fn set_mode_id(&mut self,mode_id:gameplay_modes::ModeId){ pub fn set_mode_id(&mut self,mode_id:gameplay_modes::ModeId){
@ -278,7 +278,7 @@ mod gameplay{
self.clear_checkpoints(); self.clear_checkpoints();
self.stage_id=stage_id; self.stage_id=stage_id;
} }
pub const fn accumulate_ordered_checkpoint(&mut self,stage:&gameplay_modes::Stage,model_id:ModelId){ pub fn accumulate_ordered_checkpoint(&mut self,stage:&gameplay_modes::Stage,model_id:ModelId){
if stage.is_next_ordered_checkpoint(self.get_next_ordered_checkpoint_id(),model_id){ if stage.is_next_ordered_checkpoint(self.get_next_ordered_checkpoint_id(),model_id){
self.next_ordered_checkpoint_id=gameplay_modes::CheckpointId::new(self.next_ordered_checkpoint_id.get()+1); self.next_ordered_checkpoint_id=gameplay_modes::CheckpointId::new(self.next_ordered_checkpoint_id.get()+1);
} }
@ -359,7 +359,7 @@ impl StyleHelper for StyleModifiers{
fn allow_strafe(&self,controls:u32)->bool{ fn allow_strafe(&self,controls:u32)->bool{
//disable strafing according to strafe settings //disable strafing according to strafe settings
self.strafe.is_some_and(|s|s.mask(controls)) self.strafe.as_ref().is_some_and(|s|s.mask(controls))
} }
fn get_control_dir(&self,controls:u32)->Planar64Vec3{ fn get_control_dir(&self,controls:u32)->Planar64Vec3{
@ -1003,7 +1003,7 @@ impl PhysicsContext{
let convex_mesh_aabb_list=self.data.models.models.iter() let convex_mesh_aabb_list=self.data.models.models.iter()
.flat_map(|(&model_id,model)|{ .flat_map(|(&model_id,model)|{
self.data.models.meshes[&model.mesh_id].submesh_views() self.data.models.meshes[&model.mesh_id].submesh_views()
.enumerate().map(|(submesh_id,view)|{ .enumerate().map(move|(submesh_id,view)|{
let mut aabb=aabb::Aabb::default(); let mut aabb=aabb::Aabb::default();
for v in view.verts(){ for v in view.verts(){
aabb.grow(v) aabb.grow(v)
@ -1036,7 +1036,7 @@ impl PhysicsContext{
MoveState::Walk(WalkState{state,contact,jump_direction:_})=>{ MoveState::Walk(WalkState{state,contact,jump_direction:_})=>{
let n=contact_normal(&data.models,&data.hitbox_mesh,contact); let n=contact_normal(&data.models,&data.hitbox_mesh,contact);
let gravity=s.touching.base_acceleration(&data.models,&s.style,&s.camera,s.controls,&s.next_mouse,s.time); let gravity=s.touching.base_acceleration(&data.models,&s.style,&s.camera,s.controls,&s.next_mouse,s.time);
let mut a; let a;
let mut v=s.style.get_walk_target_velocity(&s.camera,s.controls,&s.next_mouse,s.time,&n); let mut v=s.style.get_walk_target_velocity(&s.camera,s.controls,&s.next_mouse,s.time,&n);
s.touching.constrain_velocity(&data.models,&data.hitbox_mesh,&mut v); s.touching.constrain_velocity(&data.models,&data.hitbox_mesh,&mut v);
let normal_accel=-n.dot(gravity)/n.length(); let normal_accel=-n.dot(gravity)/n.length();
@ -1045,8 +1045,8 @@ impl PhysicsContext{
}, },
MoveState::Ladder(WalkState{state,contact,jump_direction:_})=>{ MoveState::Ladder(WalkState{state,contact,jump_direction:_})=>{
let n=contact_normal(&data.models,&data.hitbox_mesh,contact); let n=contact_normal(&data.models,&data.hitbox_mesh,contact);
let gravity=s.touching.base_acceleration(&data.models,&s.style,&s.camera,s.controls,&s.next_mouse,s.time); //let gravity=s.touching.base_acceleration(&data.models,&s.style,&s.camera,s.controls,&s.next_mouse,s.time);
let mut a; let a;
let mut v=s.style.get_ladder_target_velocity(&s.camera,s.controls,&s.next_mouse,s.time,&n); let mut v=s.style.get_ladder_target_velocity(&s.camera,s.controls,&s.next_mouse,s.time,&n);
s.touching.constrain_velocity(&data.models,&data.hitbox_mesh,&mut v); s.touching.constrain_velocity(&data.models,&data.hitbox_mesh,&mut v);
(*state,a)=WalkEnum::with_target_velocity(&s.body,&s.style,v,&n,s.style.ladder_speed,s.style.ladder_accel); (*state,a)=WalkEnum::with_target_velocity(&s.body,&s.style,v,&n,s.style.ladder_speed,s.style.ladder_accel);
@ -1069,11 +1069,10 @@ impl PhysicsContext{
aabb.inflate(state.style.hitbox.halfsize); aabb.inflate(state.style.hitbox.halfsize);
//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();
data.bvh.the_tester(&aabb,&mut |convex_mesh_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(convex_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,data.hitbox_mesh.transformed_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))})
@ -1170,7 +1169,7 @@ fn teleport_to_spawn(body:&mut Body,touching:&mut TouchingState,style:&StyleModi
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>,mode_state:&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>{ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,models:&PhysicsModels,mode:&gameplay_modes::Mode,style:&StyleModifiers,hitbox_mesh:&HitboxMesh,mode_state:&mut ModeState,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
@ -1275,7 +1274,8 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,mode_s
let (walk_state,a)=WalkState::ladder(&state.body,&state.style,gravity,target_velocity,contact.clone(),&normal); let (walk_state,a)=WalkState::ladder(&state.body,&state.style,gravity,target_velocity,contact.clone(),&normal);
state.move_state=MoveState::Ladder(walk_state); state.move_state=MoveState::Ladder(walk_state);
set_acceleration(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,a); set_acceleration(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,a);
} },
Some(gameplay_attributes::ContactingBehaviour::NoJump)=>todo!("nyi"),
None=>if state.style.surf_slope.map_or(true,|s|contact_normal(&data.models,&data.hitbox_mesh,contact).walkable(s,Planar64Vec3::Y)){ None=>if state.style.surf_slope.map_or(true,|s|contact_normal(&data.models,&data.hitbox_mesh,contact).walkable(s,Planar64Vec3::Y)){
//ground //ground
let gravity=state.touching.base_acceleration(&data.models,&state.style,&state.camera,state.controls,&state.next_mouse,state.time); let gravity=state.touching.base_acceleration(&data.models,&state.style,&state.camera,state.controls,&state.next_mouse,state.time);
@ -1289,7 +1289,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,mode_s
//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.get_mode_id()).unwrap(),&state.style,&data.hitbox_mesh,&mut state.touching,&mut state.body,convex_mesh_id); run_teleport_behaviour(&general.wormhole,&data.models,&data.modes.get_mode(state.mode_state.get_mode_id()).unwrap(),&state.style,&data.hitbox_mesh,&mut state.mode_state,&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{
@ -1333,7 +1333,7 @@ fn run_teleport_behaviour(wormhole:&Option<gameplay_attributes::Wormhole>,mode_s
(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.get_mode_id()).unwrap(),&state.style,&data.hitbox_mesh,&mut state.touching,&mut state.body,convex_mesh_id); run_teleport_behaviour(&general.wormhole,&data.models,&data.modes.get_mode(state.mode_state.get_mode_id()).unwrap(),&state.style,&data.hitbox_mesh,&mut state.mode_state,&mut state.touching,&mut state.body,convex_mesh_id);
}, },
_=>panic!("invalid pair"), _=>panic!("invalid pair"),
} }

View File

@ -27,6 +27,7 @@ impl WindowContext<'_>{
fn window_event(&mut self,time:integer::Time,event: winit::event::WindowEvent) { fn window_event(&mut self,time:integer::Time,event: winit::event::WindowEvent) {
match event { match event {
winit::event::WindowEvent::DroppedFile(path)=>{ winit::event::WindowEvent::DroppedFile(path)=>{
let path=path.as_path();
//blocking because it's simpler... //blocking because it's simpler...
if let Ok(file)=std::fs::File::open(path){ if let Ok(file)=std::fs::File::open(path){
// match strafesnet_snf::read_snf(std::io::BufReader::new(file)){ // match strafesnet_snf::read_snf(std::io::BufReader::new(file)){