From ec8c89de9ca164716c9667ba3698627420cd2fe9 Mon Sep 17 00:00:00 2001 From: Quaternions Date: Fri, 13 Sep 2024 13:51:33 -0700 Subject: [PATCH] many work --- src/model_physics.rs | 76 ++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/src/model_physics.rs b/src/model_physics.rs index e99d44e..b045aae 100644 --- a/src/model_physics.rs +++ b/src/model_physics.rs @@ -1,7 +1,8 @@ use std::borrow::{Borrow,Cow}; use std::collections::{HashSet,HashMap}; +use strafesnet_common::integer::vec3::Vector3; use strafesnet_common::model::{self,MeshId,PolygonIter}; -use strafesnet_common::integer::{self,vec3,Fixed,Planar64,Planar64Vec3}; +use strafesnet_common::integer::{self,vec3,Fixed,Planar64,Planar64Vec3,Ratio}; pub trait UndirectedEdge{ type DirectedEdge:Copy+DirectedEdge; @@ -63,6 +64,9 @@ struct Face{ } struct Vert(Planar64Vec3); pub trait MeshQuery{ + // Vertex must be Planar64Vec3 because it represents an actual position + type Normal; + type Offset; fn edge_n(&self,edge_id:EDGE::UndirectedEdge)->Planar64Vec3{ let verts=self.edge_verts(edge_id); self.vert(verts[1].clone())-self.vert(verts[0].clone()) @@ -72,7 +76,7 @@ pub trait MeshQuery{ (self.vert(verts[1].clone())-self.vert(verts[0].clone()))*((directed_edge_id.parity() as i64)*2-1) } fn vert(&self,vert_id:VERT)->Planar64Vec3; - fn face_nd(&self,face_id:FACE)->(Planar64Vec3,Planar64); + fn face_nd(&self,face_id:FACE)->(Self::Normal,Self::Offset); fn face_edges(&self,face_id:FACE)->Cow>; fn edge_faces(&self,edge_id:EDGE::UndirectedEdge)->Cow<[FACE;2]>; fn edge_verts(&self,edge_id:EDGE::UndirectedEdge)->Cow<[VERT;2]>; @@ -329,7 +333,7 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{ for poly_vertices in polygon_group.polys(){ let submesh_face_id=SubmeshFaceId::new(submesh_faces.len() as u32); //one face per poly - let mut normal=vec3::ZERO; + let mut normal=Vector3::new([Fixed::ZERO,Fixed::ZERO,Fixed::ZERO]); let len=poly_vertices.len(); let face_edges=poly_vertices.into_iter().enumerate().map(|(i,vert_id)|{ let vert0_id=MeshVertId::new(mesh.unique_vertices[vert_id.get() as usize].pos.get() as u32); @@ -340,7 +344,7 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{ //https://www.khronos.org/opengl/wiki/Calculating_a_Surface_Normal (Newell's Method) let v0=mesh.unique_pos[vert0_id.get() as usize]; let v1=mesh.unique_pos[vert1_id.get() as usize]; - normal+=Planar64Vec3::new([ + normal+=Vector3::new([ (v0.y-v1.y)*(v0.z+v1.z), (v0.z-v1.z)*(v0.x+v1.x), (v0.x-v1.x)*(v0.y+v1.y), @@ -361,14 +365,16 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{ //return directed_edge_id edge_id.as_directed(is_sorted) }).collect(); - //choose precision loss randomly idk - normal=normal/len as i64; - let mut dot=Planar64::ZERO; + let mut dot=Fixed::ZERO; + // find the average dot for &v in poly_vertices{ dot+=normal.dot(mesh.unique_pos[mesh.unique_vertices[v.get() as usize].pos.get() as usize]); } //assume face hash is stable, and there are no flush faces... - let face=Face{normal,dot:dot/len as i64}; + let face=Face{ + normal:(normal/len as i64).divide().fix_1(), + dot:(dot/(len*len) as i64).fix_1(), + }; let face_id=match face_id_from_face.get(&face){ Some(&face_id)=>face_id, None=>{ @@ -415,6 +421,8 @@ pub struct PhysicsMeshView<'a>{ topology:&'a PhysicsMeshTopology, } impl MeshQuery for PhysicsMeshView<'_>{ + type Normal=Planar64Vec3; + type Offset=Planar64; fn face_nd(&self,face_id:SubmeshFaceId)->(Planar64Vec3,Planar64){ 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) @@ -487,14 +495,16 @@ impl TransformedMesh<'_>{ } } impl MeshQuery for TransformedMesh<'_>{ - fn face_nd(&self,face_id:SubmeshFaceId)->(Planar64Vec3,Planar64){ + type Normal=Vector3>; + type Offset=Fixed<4,128>; + fn face_nd(&self,face_id:SubmeshFaceId)->(Self::Normal,Self::Offset){ let (n,d)=self.view.face_nd(face_id); let transformed_n=self.transform.normal*n; - let transformed_d=d+transformed_n.dot(self.transform.vertex.translation); + let transformed_d=d.fix_4()+transformed_n.dot(self.transform.vertex.translation); (transformed_n,transformed_d) } fn vert(&self,vert_id:SubmeshVertId)->Planar64Vec3{ - self.transform.vertex.transform_point3(self.view.vert(vert_id)) + self.transform.vertex.transform_point3(self.view.vert(vert_id)).fix_1() } #[inline] fn face_edges(&self,face_id:SubmeshFaceId)->Cow>{ @@ -737,9 +747,9 @@ impl MinkowskiMesh<'_>{ let verts=self.edge_verts(directed_edge_id.as_undirected()); let d=n.dot(self.vert(verts[0])+self.vert(verts[1])); //WARNING! d outside of *2 - for t in Fixed::<3,96>::zeroes2((n.dot(relative_body.position))*2-d,n.dot(relative_body.velocity)*2,n.dot(relative_body.acceleration)){ - let t=relative_body.time+integer::Time::from(t); - if relative_body.time::zeroes2((n.dot(relative_body.position))*2-d,n.dot(relative_body.velocity)*2,n.dot(relative_body.acceleration)){ + let t=relative_body.time.to_ratio().add_ratio(t); + if relative_body.time.to_ratio().lt_ratio(t)&&t.lt_ratio(best_time)&&n.dot(relative_body.extrapolated_velocity(t)).is_negative(){ best_time=t; best_edge=Some(directed_edge_id); break; @@ -767,7 +777,9 @@ impl MinkowskiMesh<'_>{ } } impl MeshQuery for MinkowskiMesh<'_>{ - fn face_nd(&self,face_id:MinkowskiFace)->(Planar64Vec3,Planar64){ + type Normal=Vector3>; + type Offset=Fixed<4,128>; + fn face_nd(&self,face_id:MinkowskiFace)->(Self::Normal,Self::Offset){ match face_id{ MinkowskiFace::VertFace(v0,f1)=>{ let (n,d)=self.mesh1.face_nd(f1); @@ -781,7 +793,7 @@ impl MeshQuery for MinkowskiM let n=edge0_n.cross(edge1_n); let e0d=n.dot(self.mesh0.vert(e0v0)+self.mesh0.vert(e0v1)); let e1d=n.dot(self.mesh1.vert(e1v0)+self.mesh1.vert(e1v1)); - (n*(parity as i64*4-2),(e0d-e1d)*(parity as i64*2-1)) + ((n*(parity as i64*4-2)).fix_3(),((e0d-e1d)*(parity as i64*2-1)).fix_4()) }, MinkowskiFace::FaceVert(f0,v1)=>{ let (n,d)=self.mesh0.face_nd(f0); @@ -830,17 +842,18 @@ impl MeshQuery for MinkowskiM let &[e1f0,e1f1]=self.mesh1.edge_faces(e1).borrow(); Cow::Owned([(e1f1,false),(e1f0,true)].map(|(edge_face_id1,face_parity)|{ let mut best_edge=None; - let mut best_d=Planar64::ZERO; + let mut best_d:Ratio,Fixed<8,256>>=Ratio::new(Fixed::ZERO,Fixed::ONE); let edge_face1_n=self.mesh1.face_nd(edge_face_id1).0; let edge_face1_nn=edge_face1_n.dot(edge_face1_n); for &directed_edge_id0 in v0e.iter(){ let edge0_n=self.mesh0.directed_edge_n(directed_edge_id0); //must be behind other face. let d=edge_face1_n.dot(edge0_n); - if d for MinkowskiM let &[e0f0,e0f1]=self.mesh0.edge_faces(e0).borrow(); Cow::Owned([(e0f0,true),(e0f1,false)].map(|(edge_face_id0,face_parity)|{ let mut best_edge=None; - let mut best_d=Planar64::ZERO; + let mut best_d:Ratio,Fixed<8,256>>=Ratio::new(Fixed::ZERO,Fixed::ONE); let edge_face0_n=self.mesh0.face_nd(edge_face_id0).0; let edge_face0_nn=edge_face0_n.dot(edge_face0_n); for &directed_edge_id1 in v1e.iter(){ let edge1_n=self.mesh1.directed_edge_n(directed_edge_id1); let d=edge_face0_n.dot(edge1_n); - if d for MinkowskiM //detect shared volume when the other mesh is mirrored along a test edge dir let v0f=self.mesh0.vert_faces(v0); let v1f=self.mesh1.vert_faces(v1); - let v0f_n:Vec=v0f.iter().map(|&face_id|self.mesh0.face_nd(face_id).0).collect(); - let v1f_n:Vec=v1f.iter().map(|&face_id|self.mesh1.face_nd(face_id).0).collect(); + let v0f_n:Vec<_>=v0f.iter().map(|&face_id|self.mesh0.face_nd(face_id).0).collect(); + let v1f_n:Vec<_>=v1f.iter().map(|&face_id|self.mesh1.face_nd(face_id).0).collect(); let the_len=v0f.len()+v1f.len(); for &directed_edge_id in self.mesh0.vert_edges(v0).iter(){ let n=self.mesh0.directed_edge_n(directed_edge_id); let nn=n.dot(n); + // TODO: there's gotta be a better way to do this //make a set of faces let mut face_normals=Vec::with_capacity(the_len); //add mesh0 faces as-is face_normals.clone_from(&v0f_n); for face_n in &v1f_n{ //add reflected mesh1 faces - face_normals.push(*face_n-n*(face_n.dot(n)*2/nn)); + face_normals.push(*face_n-(n*face_n.dot(n)*2/nn).divide().fix_3()); } if is_empty_volume(face_normals){ edges.push(MinkowskiDirectedEdge::EdgeVert(directed_edge_id,v1)); @@ -927,7 +941,7 @@ impl MeshQuery for MinkowskiM let mut face_normals=Vec::with_capacity(the_len); face_normals.clone_from(&v1f_n); for face_n in &v0f_n{ - face_normals.push(*face_n-n*(face_n.dot(n)*2/nn)); + face_normals.push(*face_n-(n*face_n.dot(n)*2/nn).divide().fix_3()); } if is_empty_volume(face_normals){ edges.push(MinkowskiDirectedEdge::VertEdge(v0,directed_edge_id)); @@ -942,12 +956,12 @@ impl MeshQuery for MinkowskiM } } -fn is_empty_volume(normals:Vec)->bool{ +fn is_empty_volume(normals:Vec>>)->bool{ let len=normals.len(); for i in 0..len-1{ for j in i+1..len{ let n=normals[i].cross(normals[j]); - let mut d_comp:Option>=None; + let mut d_comp:Option>=None; for k in 0..len{ if k!=i&&k!=j{ let d=n.dot(normals[k]); @@ -967,8 +981,8 @@ fn is_empty_volume(normals:Vec)->bool{ #[test] fn test_is_empty_volume(){ - assert!(!is_empty_volume([vec3::X,vec3::Y,vec3::Z].to_vec())); - assert!(is_empty_volume([vec3::X,vec3::Y,vec3::Z,vec3::NEG_X].to_vec())); + assert!(!is_empty_volume([vec3::X.fix_3(),vec3::Y.fix_3(),vec3::Z.fix_3()].to_vec())); + assert!(is_empty_volume([vec3::X.fix_3(),vec3::Y.fix_3(),vec3::Z.fix_3(),vec3::NEG_X.fix_3()].to_vec())); } #[test]