diff --git a/engine/physics/src/body.rs b/engine/physics/src/body.rs index e3fd5b893..568cf659e 100644 --- a/engine/physics/src/body.rs +++ b/engine/physics/src/body.rs @@ -42,12 +42,12 @@ impl<T> Body<T> pub fn extrapolated_position(&self,time:Time<T>)->Planar64Vec3{ let dt=time-self.time; self.position - +(self.velocity*dt).map(|elem|elem.divide().fix_1()) - +self.acceleration.map(|elem|(dt*dt*elem/2).divide().fix_1()) + +(self.velocity*dt).map(|elem|elem.divide().clamp_1()) + +self.acceleration.map(|elem|(dt*dt*elem/2).divide().clamp_1()) } pub fn extrapolated_velocity(&self,time:Time<T>)->Planar64Vec3{ let dt=time-self.time; - self.velocity+(self.acceleration*dt).map(|elem|elem.divide().fix_1()) + self.velocity+(self.acceleration*dt).map(|elem|elem.divide().clamp_1()) } pub fn advance_time(&mut self,time:Time<T>){ self.position=self.extrapolated_position(time); @@ -71,12 +71,12 @@ impl<T> Body<T> D2:Copy, Planar64:core::ops::Mul<D2,Output=N4>, N4:integer::Divide<D2,Output=T1>, - T1:integer::Fix<Planar64>, + T1:integer::Clamp<Planar64>, { // a*dt^2/2 + v*dt + p // (a*dt/2+v)*dt+p (self.acceleration.map(|elem|dt*elem/2)+self.velocity).map(|elem|dt.mul_ratio(elem)) - .map(|elem|elem.divide().fix())+self.position + .map(|elem|elem.divide().clamp())+self.position } pub fn extrapolated_velocity_ratio_dt<Num,Den,N1,T1>(&self,dt:integer::Ratio<Num,Den>)->Planar64Vec3 where @@ -85,10 +85,10 @@ impl<T> Body<T> Num:core::ops::Mul<Planar64,Output=N1>, Planar64:core::ops::Mul<Den,Output=N1>, N1:integer::Divide<Den,Output=T1>, - T1:integer::Fix<Planar64>, + T1:integer::Clamp<Planar64>, { // a*dt + v - self.acceleration.map(|elem|(dt*elem).divide().fix())+self.velocity + self.acceleration.map(|elem|(dt*elem).divide().clamp())+self.velocity } pub fn advance_time_ratio_dt(&mut self,dt:crate::model::GigaTime){ self.position=self.extrapolated_position_ratio_dt(dt); diff --git a/engine/physics/src/face_crawler.rs b/engine/physics/src/face_crawler.rs index b0df763c1..0d10cb6b8 100644 --- a/engine/physics/src/face_crawler.rs +++ b/engine/physics/src/face_crawler.rs @@ -63,7 +63,8 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M> let &[v0,v1]=mesh.edge_verts(directed_edge_id.as_undirected()).as_ref(); //WARNING: d is moved out of the *2 block because of adding two vertices! //WARNING: precision is swept under the rug! - for dt in Fixed::<4,128>::zeroes2(n.dot(body.position*2-(mesh.vert(v0)+mesh.vert(v1))).fix_4(),n.dot(body.velocity).fix_4()*2,n.dot(body.acceleration).fix_4()){ + //wrap for speed + for dt in Fixed::<4,128>::zeroes2(n.dot(body.position*2-(mesh.vert(v0)+mesh.vert(v1))).wrap_4(),n.dot(body.velocity).wrap_4()*2,n.dot(body.acceleration).wrap_4()){ if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ best_time=dt; best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt); @@ -84,7 +85,8 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M> //edge_n gets parity from the order of edge_faces let n=face_n.cross(edge_n)*((i as i64)*2-1); //WARNING yada yada d *2 - for dt in Fixed::<4,128>::zeroes2(n.dot(delta_pos).fix_4(),n.dot(body.velocity).fix_4()*2,n.dot(body.acceleration).fix_4()){ + //wrap for speed + for dt in Fixed::<4,128>::zeroes2(n.dot(delta_pos).wrap_4(),n.dot(body.velocity).wrap_4()*2,n.dot(body.acceleration).wrap_4()){ if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ best_time=dt; best_transition=Transition::Next(FEV::Face(edge_face_id),dt); @@ -98,7 +100,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M> let n=edge_n*(1-2*(i as i64)); for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){ if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ - let dt=Ratio::new(dt.num.fix_4(),dt.den.fix_4()); + let dt=Ratio::new(dt.num.widen_4(),dt.den.widen_4()); best_time=dt; best_transition=Transition::Next(FEV::Vert(vert_id),dt); break; @@ -114,7 +116,7 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M> let n=-mesh.directed_edge_n(directed_edge_id); for dt in Fixed::<2,64>::zeroes2((n.dot(body.position-mesh.vert(vert_id)))*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){ if body_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ - let dt=Ratio::new(dt.num.fix_4(),dt.den.fix_4()); + let dt=Ratio::new(dt.num.widen_4(),dt.den.widen_4()); best_time=dt; best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt); break; @@ -129,11 +131,11 @@ impl<F:Copy,M:MeshQuery<Normal=Vector3<F>,Offset=Fixed<4,128>>> FEV<M> pub fn crawl(mut self,mesh:&M,relative_body:&Body,start_time:Time,time_limit:Time)->CrawlResult<M>{ let mut body_time={ let r=(start_time-relative_body.time).to_ratio(); - Ratio::new(r.num.fix_4(),r.den.fix_4()) + Ratio::new(r.num.widen_4(),r.den.widen_4()) }; let time_limit={ let r=(time_limit-relative_body.time).to_ratio(); - Ratio::new(r.num.fix_4(),r.den.fix_4()) + Ratio::new(r.num.widen_4(),r.den.widen_4()) }; for _ in 0..20{ match self.next_transition(body_time,mesh,relative_body,time_limit){ diff --git a/engine/physics/src/model.rs b/engine/physics/src/model.rs index 0269a857c..2c4aece91 100644 --- a/engine/physics/src/model.rs +++ b/engine/physics/src/model.rs @@ -378,8 +378,8 @@ impl TryFrom<&model::Mesh> for PhysicsMesh{ } //assume face hash is stable, and there are no flush faces... let face=Face{ - normal:(normal/len as i64).divide().fix_1(), - dot:(dot/(len*len) as i64).fix_1(), + normal:(normal/len as i64).divide().narrow_1().unwrap(), + dot:(dot/(len*len) as i64).narrow_1().unwrap(), }; let face_id=match face_id_from_face.get(&face){ Some(&face_id)=>face_id, @@ -519,7 +519,8 @@ impl MeshQuery for TransformedMesh<'_>{ (transformed_n,transformed_d) } fn vert(&self,vert_id:SubmeshVertId)->Planar64Vec3{ - self.transform.vertex.transform_point3(self.view.vert(vert_id)).fix_1() + // wrap for speed + self.transform.vertex.transform_point3(self.view.vert(vert_id)).wrap_1() } #[inline] fn face_edges(&self,face_id:SubmeshFaceId)->impl AsRef<[SubmeshDirectedEdgeId]>{ @@ -659,7 +660,8 @@ impl MinkowskiMesh<'_>{ if !d.is_negative()&&d<=edge_nn{ let distance_squared={ let c=diff.cross(edge_n); - (c.dot(c)/edge_nn).divide().fix_2() + //wrap for speed + (c.dot(c)/edge_nn).divide().wrap_2() }; if distance_squared<=*best_distance_squared{ best_transition=EV::Edge(directed_edge_id.as_undirected()); @@ -764,7 +766,7 @@ impl MinkowskiMesh<'_>{ }; let mut best_time={ let r=(time_limit-relative_body.time).to_ratio(); - Ratio::new(r.num.fix_4(),r.den.fix_4()) + Ratio::new(r.num.widen_4(),r.den.widen_4()) }; let mut best_edge=None; let face_n=self.face_nd(contact_face_id).0; @@ -776,7 +778,8 @@ impl MinkowskiMesh<'_>{ let d=n.dot(self.vert(v0)+self.vert(v1)); //WARNING! d outside of *2 //WARNING: truncated precision - for dt in Fixed::<4,128>::zeroes2(((n.dot(relative_body.position))*2-d).fix_4(),n.dot(relative_body.velocity).fix_4()*2,n.dot(relative_body.acceleration).fix_4()){ + //wrap for speed + for dt in Fixed::<4,128>::zeroes2(((n.dot(relative_body.position))*2-d).wrap_4(),n.dot(relative_body.velocity).wrap_4()*2,n.dot(relative_body.acceleration).wrap_4()){ if start_time.le_ratio(dt)&&dt.lt_ratio(best_time)&&n.dot(relative_body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ best_time=dt; best_edge=Some(directed_edge_id); @@ -822,7 +825,7 @@ impl MeshQuery for MinkowskiMesh<'_>{ 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)).fix_3(),((e0d-e1d)*(parity as i64*2-1)).fix_4()) + ((n*(parity as i64*4-2)).widen_3(),((e0d-e1d)*(parity as i64*2-1)).widen_4()) }, MinkowskiFace::FaceVert(f0,v1)=>{ let (n,d)=self.mesh0.face_nd(f0); @@ -954,7 +957,8 @@ impl MeshQuery for MinkowskiMesh<'_>{ 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).divide().fix_3()); + //wrap for speed + face_normals.push(*face_n-(n*face_n.dot(n)*2/nn).divide().wrap_3()); } if is_empty_volume(face_normals){ edges.push(MinkowskiDirectedEdge::EdgeVert(directed_edge_id,v1)); @@ -966,7 +970,8 @@ impl MeshQuery for MinkowskiMesh<'_>{ 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).divide().fix_3()); + //wrap for speed + face_normals.push(*face_n-(n*face_n.dot(n)*2/nn).divide().wrap_3()); } if is_empty_volume(face_normals){ edges.push(MinkowskiDirectedEdge::VertEdge(v0,directed_edge_id)); @@ -1008,6 +1013,6 @@ fn is_empty_volume(normals:Vec<Vector3<Fixed<3,96>>>)->bool{ #[test] fn test_is_empty_volume(){ - 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())); + assert!(!is_empty_volume([vec3::X.widen_3(),vec3::Y.widen_3(),vec3::Z.widen_3()].to_vec())); + assert!(is_empty_volume([vec3::X.widen_3(),vec3::Y.widen_3(),vec3::Z.widen_3(),vec3::NEG_X.widen_3()].to_vec())); } diff --git a/engine/physics/src/physics.rs b/engine/physics/src/physics.rs index 8644cb3ac..aaee9119c 100644 --- a/engine/physics/src/physics.rs +++ b/engine/physics/src/physics.rs @@ -117,8 +117,8 @@ impl TransientAcceleration{ }else{ //normal friction acceleration is clippedAcceleration.dot(normal)*friction TransientAcceleration::Reachable{ - acceleration:target_diff.with_length(accel).divide().fix_1(), - time:time+Time::from((target_diff.length()/accel).divide().fix_1()) + acceleration:target_diff.with_length(accel).divide().wrap_1(), + time:time+Time::from((target_diff.length()/accel).divide().clamp_1()) } } } @@ -407,7 +407,7 @@ impl HitboxMesh{ let transform=PhysicsMeshTransform::new(transform); let transformed_mesh=TransformedMesh::new(mesh.complete_mesh_view(),&transform); for vert in transformed_mesh.verts(){ - aabb.grow(vert.fix_1()); + aabb.grow(vert.narrow_1().unwrap()); } Self{ halfsize:aabb.size()>>1, @@ -460,12 +460,12 @@ impl StyleHelper for StyleModifiers{ } fn get_y_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{ - (camera.rotation_y()*self.get_control_dir(controls)).fix_1() + (camera.rotation_y()*self.get_control_dir(controls)).wrap_1() } fn get_propulsion_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{ //don't interpolate this! discrete mouse movement, constant acceleration - (camera.rotation()*self.get_control_dir(controls)).fix_1() + (camera.rotation()*self.get_control_dir(controls)).wrap_1() } fn calculate_mesh(&self)->HitboxMesh{ let mesh=match self.hitbox.mesh{ @@ -1084,7 +1084,7 @@ impl PhysicsData{ let mut aabb=aabb::Aabb::default(); let transformed_mesh=TransformedMesh::new(view,transform); for v in transformed_mesh.verts(){ - aabb.grow(v.fix_1()); + aabb.grow(v.narrow_1().unwrap()); } (ConvexMeshId{ model_id, @@ -1162,7 +1162,8 @@ fn contact_normal(models:&PhysicsModels,hitbox_mesh:&HitboxMesh,contact:&Contact let model_mesh=models.contact_mesh(contact); let minkowski=model_physics::MinkowskiMesh::minkowski_sum(model_mesh,hitbox_mesh.transformed_mesh()); // TODO: normalize to i64::MAX>>1 - minkowski.face_nd(contact.face_id).0.fix_1() + // wrap for speed + minkowski.face_nd(contact.face_id).0.wrap_1() } fn recalculate_touching( @@ -1321,7 +1322,7 @@ fn teleport_to_spawn( const EPSILON:Planar64=Planar64::raw((1<<32)/16); let transform=models.get_model_transform(spawn_model_id).ok_or(TeleportToSpawnError::NoModel)?; //TODO: transform.vertex.matrix3.col(1)+transform.vertex.translation - let point=transform.vertex.transform_point3(vec3::Y).fix_1()+Planar64Vec3::new([Planar64::ZERO,style.hitbox.halfsize.y+EPSILON,Planar64::ZERO]); + let point=transform.vertex.transform_point3(vec3::Y).clamp_1()+Planar64Vec3::new([Planar64::ZERO,style.hitbox.halfsize.y+EPSILON,Planar64::ZERO]); teleport(point,move_state,body,touching,run,mode_state,Some(mode),models,hitbox_mesh,bvh,style,camera,input_state,time); Ok(()) } @@ -1485,7 +1486,7 @@ fn collision_start_contact( Some(gameplay_attributes::ContactingBehaviour::Surf)=>(), Some(gameplay_attributes::ContactingBehaviour::Cling)=>println!("Unimplemented!"), &Some(gameplay_attributes::ContactingBehaviour::Elastic(elasticity))=>{ - let reflected_velocity=body.velocity+((body.velocity-incident_velocity)*Planar64::raw(elasticity as i64+1)).fix_1(); + let reflected_velocity=body.velocity+((body.velocity-incident_velocity)*Planar64::raw(elasticity as i64+1)).wrap_1(); set_velocity(body,touching,models,hitbox_mesh,reflected_velocity); }, Some(gameplay_attributes::ContactingBehaviour::Ladder(contacting_ladder))=> @@ -1708,7 +1709,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim let control_dir=state.style.get_control_dir(masked_controls); if control_dir!=vec3::ZERO{ let camera_mat=state.camera.simulate_move_rotation_y(state.input_state.lerp_delta(state.time).x); - if let Some(ticked_velocity)=strafe_settings.tick_velocity(state.body.velocity,(camera_mat*control_dir).with_length(Planar64::ONE).divide().fix_1()){ + if let Some(ticked_velocity)=strafe_settings.tick_velocity(state.body.velocity,(camera_mat*control_dir).with_length(Planar64::ONE).divide().wrap_1()){ //this is wrong but will work ig //need to note which push planes activate in push solve and keep those state.cull_velocity(data,ticked_velocity); diff --git a/engine/physics/src/push_solve.rs b/engine/physics/src/push_solve.rs index 5b1c5a7e4..7432a19c3 100644 --- a/engine/physics/src/push_solve.rs +++ b/engine/physics/src/push_solve.rs @@ -152,18 +152,19 @@ const fn get_push_ray_0(point:Planar64Vec3)->Ray{ Ray{origin:point,direction:vec3::ZERO} } fn get_push_ray_1(point:Planar64Vec3,c0:&Contact)->Option<Ray>{ - let direction=solve1(c0)?.divide().fix_1(); + //wrap for speed + let direction=solve1(c0)?.divide().wrap_1(); let [s0]=decompose1(direction,c0.velocity)?; if s0.lt_ratio(RATIO_ZERO){ return None; } let origin=point+solve1( &c0.relative_to(point), - )?.divide().fix_1(); + )?.divide().wrap_1(); Some(Ray{origin,direction}) } fn get_push_ray_2(point:Planar64Vec3,c0:&Contact,c1:&Contact)->Option<Ray>{ - let direction=solve2(c0,c1)?.divide().fix_1(); + let direction=solve2(c0,c1)?.divide().wrap_1(); let [s0,s1]=decompose2(direction,c0.velocity,c1.velocity)?; if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO){ return None; @@ -171,11 +172,11 @@ fn get_push_ray_2(point:Planar64Vec3,c0:&Contact,c1:&Contact)->Option<Ray>{ let origin=point+solve2( &c0.relative_to(point), &c1.relative_to(point), - )?.divide().fix_1(); + )?.divide().wrap_1(); Some(Ray{origin,direction}) } fn get_push_ray_3(point:Planar64Vec3,c0:&Contact,c1:&Contact,c2:&Contact)->Option<Ray>{ - let direction=solve3(c0,c1,c2)?.divide().fix_1(); + let direction=solve3(c0,c1,c2)?.divide().wrap_1(); let [s0,s1,s2]=decompose3(direction,c0.velocity,c1.velocity,c2.velocity)?; if s0.lt_ratio(RATIO_ZERO)||s1.lt_ratio(RATIO_ZERO)||s2.lt_ratio(RATIO_ZERO){ return None; @@ -184,7 +185,7 @@ fn get_push_ray_3(point:Planar64Vec3,c0:&Contact,c1:&Contact,c2:&Contact)->Optio &c0.relative_to(point), &c1.relative_to(point), &c2.relative_to(point), - )?.divide().fix_1(); + )?.divide().wrap_1(); Some(Ray{origin,direction}) }