From da3ab52fe057ec87cc8e341b88d8b2c595c2fccd Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 13 May 2025 15:22:28 -0700 Subject: [PATCH] physics: do not require complete_mesh as first submesh This removes a silent assumption about the input meshes and moves the branching from submeshes() to complete_mesh() --- engine/physics/src/model.rs | 40 ++++++++++++++++++++--------------- engine/physics/src/physics.rs | 2 +- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/engine/physics/src/model.rs b/engine/physics/src/model.rs index 9c9ab035..bddb094d 100644 --- a/engine/physics/src/model.rs +++ b/engine/physics/src/model.rs @@ -143,10 +143,12 @@ impl From for PhysicsMeshId{ pub struct PhysicsSubmeshId(u32); pub struct PhysicsMesh{ data:PhysicsMeshData, - complete_mesh:PhysicsMeshTopology, - //Most objects in roblox maps are already convex, so the list length is 0 - //as soon as the mesh is divided into 2 submeshes, the list length jumps to 2. - //length 1 is unnecessary since the complete mesh would be a duplicate of the only submesh, but would still function properly + // The complete mesh is unused at this time. + // complete_mesh:PhysicsMeshTopology, + // Submeshes are guaranteed to be convex and may contain + // "virtual" faces which are not part of the complete mesh. + // Physics calculations should never resolve to hitting + // a virtual face. submeshes:Vec, } impl PhysicsMesh{ @@ -210,19 +212,24 @@ impl PhysicsMesh{ }; Self{ data, - complete_mesh:mesh_topology, - submeshes:Vec::new(), + // complete_mesh:mesh_topology.clone(), + submeshes:vec![mesh_topology], } } pub fn unit_cylinder()->Self{ Self::unit_cube() } #[inline] - pub const fn complete_mesh(&self)->&PhysicsMeshTopology{ - &self.complete_mesh + pub fn complete_mesh(&self)->&PhysicsMeshTopology{ + // If there is exactly one submesh, then the complete mesh is identical to it. + if self.submeshes.len()==1{ + self.submeshes.first().unwrap() + }else{ + panic!("PhysicsMesh complete mesh is not known"); + } } #[inline] - pub const fn complete_mesh_view(&self)->PhysicsMeshView{ + pub fn complete_mesh_view(&self)->PhysicsMeshView{ PhysicsMeshView{ data:&self.data, topology:self.complete_mesh(), @@ -230,12 +237,7 @@ impl PhysicsMesh{ } #[inline] pub fn submeshes(&self)->&[PhysicsMeshTopology]{ - //the complete mesh is already a convex mesh when len()==0, len()==1 is invalid but will still work - if self.submeshes.len()==0{ - std::slice::from_ref(&self.complete_mesh) - }else{ - &self.submeshes.as_slice() - } + &self.submeshes } #[inline] pub fn submesh_view(&self,submesh_id:PhysicsSubmeshId)->PhysicsMeshView{ @@ -313,6 +315,10 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{ if mesh.unique_pos.len()==0{ return Err(PhysicsMeshError::ZeroVertices); } + // An empty physics mesh is a waste of resources + if mesh.physics_groups.len()==0{ + return Err(PhysicsMeshError::NoPhysicsGroups); + } let verts=mesh.unique_pos.iter().copied().map(Vert).collect(); //TODO: fix submeshes //flat map mesh.physics_groups[$1].groups.polys()[$2] as face_id @@ -320,7 +326,7 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{ //the same face is not allowed to be in multiple polygon groups let mut faces=Vec::new(); let mut face_id_from_face=HashMap::new(); - let mut mesh_topologies:Vec=mesh.physics_groups.iter().map(|physics_group|{ + let mesh_topologies:Vec=mesh.physics_groups.iter().map(|physics_group|{ //construct submesh let mut submesh_faces=Vec::new();//these contain a map from submeshId->meshId let mut submesh_verts=Vec::new(); @@ -416,7 +422,7 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{ faces, verts, }, - complete_mesh:mesh_topologies.pop().ok_or(PhysicsMeshError::NoPhysicsGroups)?, + // complete_mesh:None, submeshes:mesh_topologies, }) } diff --git a/engine/physics/src/physics.rs b/engine/physics/src/physics.rs index eee9d862..cdc176f0 100644 --- a/engine/physics/src/physics.rs +++ b/engine/physics/src/physics.rs @@ -417,7 +417,7 @@ impl HitboxMesh{ } } #[inline] - const fn transformed_mesh(&self)->TransformedMesh{ + fn transformed_mesh(&self)->TransformedMesh{ TransformedMesh::new(self.mesh.complete_mesh_view(),&self.transform) } }