From fc7d4b7e0c0c43d117543562a57bc8491e3043ab Mon Sep 17 00:00:00 2001 From: Quaternions Date: Thu, 12 Sep 2024 12:17:18 -0700 Subject: [PATCH] more wip --- src/physics.rs | 237 +++++++++++++++++++++++++------------------------ 1 file changed, 119 insertions(+), 118 deletions(-) diff --git a/src/physics.rs b/src/physics.rs index 15ff6b9..85e12fc 100644 --- a/src/physics.rs +++ b/src/physics.rs @@ -11,7 +11,7 @@ use strafesnet_common::gameplay_modes::{self,StageId}; use strafesnet_common::gameplay_style::{self,StyleModifiers}; use strafesnet_common::controls_bitflag::Controls; use strafesnet_common::instruction::{self,InstructionEmitter,InstructionConsumer,TimedInstruction}; -use strafesnet_common::integer::{self,Time,Planar64,Planar64Vec3,Planar64Mat3,Angle32,Ratio64Vec2}; +use strafesnet_common::integer::{self,vec3,mat3,Time,Planar64,Planar64Vec3,Planar64Mat3,Angle32,Ratio64Vec2}; use gameplay::ModeState; //external influence @@ -36,7 +36,7 @@ enum PhysicsInstruction{ Input(PhysicsInputInstruction), } -#[derive(Clone,Copy,Debug,Default,Hash)] +#[derive(Clone,Copy,Debug,Hash)] pub struct Body{ pub position:Planar64Vec3,//I64 where 2^32 = 1 u pub velocity:Planar64Vec3,//I64 where 2^32 = 1 u/s @@ -124,13 +124,13 @@ struct ContactMoveState{ } impl TransientAcceleration{ fn with_target_diff(target_diff:Planar64Vec3,accel:Planar64,time:Time)->Self{ - if target_diff==Planar64Vec3::ZERO{ + if target_diff==vec3::ZERO{ TransientAcceleration::Reached }else{ //normal friction acceleration is clippedAcceleration.dot(normal)*friction TransientAcceleration::Reachable{ - acceleration:target_diff.with_length(accel), - time:time+Time::from(target_diff.length()/accel) + acceleration:target_diff.with_length(accel).divide().fix_1(), + time:time+Time::from((target_diff.length()/accel).divide().fix_1()) } } } @@ -147,7 +147,7 @@ impl TransientAcceleration{ } fn acceleration(&self)->Planar64Vec3{ match self{ - TransientAcceleration::Reached=>Planar64Vec3::ZERO, + TransientAcceleration::Reached=>vec3::ZERO, &TransientAcceleration::Reachable{acceleration,time:_}=>acceleration, &TransientAcceleration::Unreachable{acceleration}=>acceleration, } @@ -158,7 +158,7 @@ impl ContactMoveState{ Self{ target:TransientAcceleration::ground(walk_settings,body,gravity,target_velocity), contact, - jump_direction:JumpDirection::Exactly(Planar64Vec3::Y), + jump_direction:JumpDirection::Exactly(vec3::Y), } } fn ladder(ladder_settings:&gameplay_style::LadderSettings,body:&Body,gravity:Planar64Vec3,target_velocity:Planar64Vec3,contact:ContactCollision)->Self{ @@ -296,7 +296,7 @@ impl PhysicsCamera{ let ay=Angle32::clamp_from_i64(a.y) //clamp to actual vertical cam limit .clamp(Self::ANGLE_PITCH_LOWER_LIMIT,Self::ANGLE_PITCH_UPPER_LIMIT); - Planar64Mat3::from_rotation_yx(ax,ay) + mat3::from_rotation_yx(ax,ay) } fn rotation(&self)->Planar64Mat3{ self.get_rotation(self.clamped_mouse_pos) @@ -306,7 +306,7 @@ impl PhysicsCamera{ } fn get_rotation_y(&self,mouse_pos_x:i32)->Planar64Mat3{ let ax=-self.sensitivity.x.mul_int(mouse_pos_x as i64); - Planar64Mat3::from_rotation_y(Angle32::wrap_from_i64(ax)) + mat3::from_rotation_y(Angle32::wrap_from_i64(ax)) } fn rotation_y(&self)->Planar64Mat3{ self.get_rotation_y(self.clamped_mouse_pos.x) @@ -438,7 +438,7 @@ impl StyleHelper for StyleModifiers{ fn get_control_dir(&self,controls:Controls)->Planar64Vec3{ //don't get fancy just do it - let mut control_dir:Planar64Vec3 = Planar64Vec3::ZERO; + let mut control_dir:Planar64Vec3 = vec3::ZERO; //Apply mask after held check so you can require non-allowed keys to be held for some reason let controls=controls.intersection(self.controls_mask); if controls.contains(Controls::MoveForward){ @@ -463,19 +463,19 @@ impl StyleHelper for StyleModifiers{ } fn get_y_control_dir(&self,camera:&PhysicsCamera,controls:Controls)->Planar64Vec3{ - camera.rotation_y()*self.get_control_dir(controls) + (camera.rotation_y()*self.get_control_dir(controls)).fix_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) + (camera.rotation()*self.get_control_dir(controls)).fix_1() } fn calculate_mesh(&self)->HitboxMesh{ let mesh=match self.hitbox.mesh{ gameplay_style::HitboxMesh::Box=>PhysicsMesh::unit_cube(), gameplay_style::HitboxMesh::Cylinder=>PhysicsMesh::unit_cylinder(), }; - let transform=Planar64Mat3::from_diagonal(self.hitbox.halfsize).extend(Planar64Vec3::ZERO); + let transform=mat3::from_diagonal(self.hitbox.halfsize).extend_column(vec3::ZERO); HitboxMesh::new(mesh,transform) } } @@ -491,7 +491,7 @@ impl MoveState{ //call this after state.move_state is changed fn apply_enum(&self,body:&mut Body,touching:&TouchingState,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,style:&StyleModifiers,camera:&PhysicsCamera,input_state:&InputState){ match self{ - MoveState::Fly=>body.acceleration=Planar64Vec3::ZERO, + MoveState::Fly=>body.acceleration=vec3::ZERO, MoveState::Air=>{ //calculate base acceleration let a=touching.base_acceleration(models,style,camera,input_state); @@ -783,7 +783,7 @@ impl TouchingState{ } } fn predict_collision_end(&self,collector:&mut instruction::InstructionCollector,models:&PhysicsModels,hitbox_mesh:&HitboxMesh,body:&Body,time:Time){ - let relative_body=VirtualBody::relative(&Body::default(),body).body(time); + let relative_body=VirtualBody::relative(&Body::ZERO,body).body(time); for contact in &self.contacts{ //detect face slide off let model_mesh=models.contact_mesh(contact); @@ -814,6 +814,7 @@ impl TouchingState{ } impl Body{ + pub const ZERO:Self=Self::new(vec3::ZERO,vec3::ZERO,vec3::ZERO,Time::ZERO); pub const fn new(position:Planar64Vec3,velocity:Planar64Vec3,acceleration:Planar64Vec3,time:Time)->Self{ Self{ position, @@ -824,11 +825,13 @@ impl Body{ } pub fn extrapolated_position(&self,time:Time)->Planar64Vec3{ let dt=time-self.time; - self.position+self.velocity*dt+self.acceleration*(dt*dt/2) + self.position + +(self.velocity*dt).map(|elem|elem.divide().fix_1()) + +self.acceleration.map(|elem|(dt*dt*elem/2).divide().fix_1()) } pub fn extrapolated_velocity(&self,time:Time)->Planar64Vec3{ let dt=time-self.time; - self.velocity+self.acceleration*dt + self.velocity+(self.acceleration*dt).map(|elem|elem.divide().fix_1()) } pub fn advance_time(&mut self,time:Time){ self.position=self.extrapolated_position(time); @@ -836,8 +839,8 @@ impl Body{ self.time=time; } pub fn infinity_dir(&self)->Option{ - if self.velocity==Planar64Vec3::ZERO{ - if self.acceleration==Planar64Vec3::ZERO{ + if self.velocity==vec3::ZERO{ + if self.acceleration==vec3::ZERO{ None }else{ Some(self.acceleration) @@ -851,19 +854,19 @@ impl Body{ aabb.grow(self.extrapolated_position(t1)); //v+a*t==0 //goober code - if self.acceleration.x!=Planar64::ZERO{ + if !self.acceleration.x.is_zero(){ let t=Time::from(-self.velocity.x/self.acceleration.x); if t0Self{ Self{ - body:Body::new(Planar64Vec3::int(0,50,0),Planar64Vec3::int(0,0,0),Planar64Vec3::int(0,-100,0),Time::ZERO), + body:Body::new(vec3::int(0,50,0),vec3::int(0,0,0),vec3::int(0,-100,0),Time::ZERO), time:Time::ZERO, style:StyleModifiers::default(), touching:TouchingState::default(), @@ -1331,12 +1334,12 @@ fn set_velocity_cull(body:&mut Body,touching:&mut TouchingState,models:&PhysicsM let mut culled=false; touching.contacts.retain(|contact|{ let n=contact_normal(models,hitbox_mesh,contact); - let r=n.dot(v)<=Planar64::ZERO; - if !r{ + let r=n.dot(v).is_positive(); + if r{ culled=true; println!("set_velocity_cull contact={:?}",contact); } - r + !r }); set_velocity(body,touching,models,hitbox_mesh,v); culled @@ -1350,12 +1353,12 @@ fn set_acceleration_cull(body:&mut Body,touching:&mut TouchingState,models:&Phys let mut culled=false; touching.contacts.retain(|contact|{ let n=contact_normal(models,hitbox_mesh,contact); - let r=n.dot(a)<=Planar64::ZERO; - if !r{ + let r=n.dot(a).is_positive(); + if r{ culled=true; println!("set_acceleration_cull contact={:?}",contact); } - r + !r }); set_acceleration(body,touching,models,hitbox_mesh,a); culled @@ -1493,7 +1496,7 @@ fn run_teleport_behaviour( } if let Some(&gameplay_attributes::Wormhole{destination_model})=wormhole{ if let (Some(origin),Some(destination))=(models.get_model_transform(model_id),models.get_model_transform(destination_model)){ - let point=body.position-origin.vertex.translation+destination.vertex.translation; + let point=body.position-origin.vertex.col(3)+destination.vertex.col(3); //TODO: camera angles teleport(point,move_state,body,touching,run,mode_state,mode,models,hitbox_mesh,bvh,style,camera,input_state,time); } @@ -1535,7 +1538,7 @@ fn collision_start_contact( //kill v //actually you could do this with a booster attribute :thinking: //it's a little bit different because maybe you want to chain ladders together - set_velocity(body,touching,models,hitbox_mesh,Planar64Vec3::ZERO);//model.velocity + set_velocity(body,touching,models,hitbox_mesh,vec3::ZERO);//model.velocity } //ladder walkstate let (gravity,target_velocity)=ladder_things(ladder_settings,&contact,touching,models,hitbox_mesh,style,camera,input_state); @@ -1725,9 +1728,9 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim if strafe_settings.activates(controls){ let masked_controls=strafe_settings.mask(controls); let control_dir=state.style.get_control_dir(masked_controls); - if control_dir!=Planar64Vec3::ZERO{ + 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)){ + if let Some(ticked_velocity)=strafe_settings.tick_velocity(state.body.velocity,(camera_mat*control_dir).with_length(Planar64::ONE).divide().fix_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); @@ -1751,7 +1754,7 @@ fn atomic_internal_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:Tim //we know that the acceleration is precisely zero because the walk target is known to be reachable //which means that gravity can be fully cancelled //ignore moving platforms for now - set_acceleration(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,Planar64Vec3::ZERO); + set_acceleration(&mut state.body,&state.touching,&data.models,&data.hitbox_mesh,vec3::ZERO); walk_state.target=TransientAcceleration::Reached; }, //you are not supposed to reach an unreachable walk target! @@ -1844,11 +1847,11 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI //TODO: spawn at the bottom of the start zone plus the hitbox size //TODO: set camera andles to face the same way as the start zone data.models.get_model_transform(mode.get_start().into()).map(|transform| - transform.vertex.translation + transform.vertex.col(3) ) - ).unwrap_or(Planar64Vec3::ZERO); + ).unwrap_or(vec3::ZERO); set_position(spawn_point,&mut state.move_state,&mut state.body,&mut state.touching,&mut state.run,&mut state.mode_state,mode,&data.models,&data.hitbox_mesh,&data.bvh,&state.style,&state.camera,&state.input_state,state.time); - 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,vec3::ZERO); state.set_move_state(data,MoveState::Air); b_refresh_walk_target=false; } @@ -1911,9 +1914,10 @@ fn atomic_input_instruction(state:&mut PhysicsState,data:&PhysicsData,ins:TimedI #[cfg(test)] mod test{ + use strafesnet_common::integer::{vec3::{self,int as int3},mat3}; use super::*; fn test_collision_axis_aligned(relative_body:Body,expected_collision_time:Option