From b05d4349432dada25f9f51a58046de2d7544ec4c Mon Sep 17 00:00:00 2001 From: Rhys Lloyd Date: Tue, 27 Jan 2026 08:30:10 -0800 Subject: [PATCH 1/3] body --- engine/physics/src/body.rs | 85 +++++++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/engine/physics/src/body.rs b/engine/physics/src/body.rs index e1b69f0b..eb4534d1 100644 --- a/engine/physics/src/body.rs +++ b/engine/physics/src/body.rs @@ -2,12 +2,18 @@ use strafesnet_common::aabb; use strafesnet_common::integer::{self,vec3,Time,Planar64,Planar64Vec3}; #[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 - pub acceleration:Planar64Vec3,//I64 where 2^32 = 1 u/s/s - pub time:Time,//nanoseconds x xxxxD! + pub position:Planar64Vec3, + pub velocity:Planar64Vec3, + pub time:Time, } -impl std::ops::Neg for Body{ +#[derive(Clone,Copy,Debug,Hash)] +pub struct Trajectory{ + pub position:Planar64Vec3, + pub velocity:Planar64Vec3, + pub acceleration:Planar64Vec3, + pub time:Time, +} +impl std::ops::Neg for Trajectory{ type Output=Self; fn neg(self)->Self::Output{ Self{ @@ -18,10 +24,10 @@ impl std::ops::Neg for Body{ } } } -impl std::ops::Neg for &Body{ - type Output=Body; +impl std::ops::Neg for &Trajectory{ + type Output=Trajectory; fn neg(self)->Self::Output{ - Body{ + Trajectory{ position:self.position, velocity:-self.velocity, acceleration:self.acceleration, @@ -32,6 +38,19 @@ impl std::ops::Neg for &Body{ impl Body where Time:Copy, +{ + pub const ZERO:Self=Self::new(vec3::zero(),vec3::zero(),Time::ZERO); + pub const fn new(position:Planar64Vec3,velocity:Planar64Vec3,time:Time)->Self{ + Self{ + position, + velocity, + time, + } + } +} + +impl Trajectory + where Time:Copy, { 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{ @@ -42,13 +61,27 @@ impl Body time, } } - pub const fn relative_to<'a>(&'a self,body0:&'a Body)->VirtualBody<'a,T>{ + pub const fn body_with_acceleration(body:Body,acceleration:Planar64Vec3)->Trajectory{ + let Body{ + position, + velocity, + time, + }=body; + Self{ + position, + velocity, + acceleration, + time, + } + } + pub fn relative_to(&self,trj0:&Trajectory,time:Time)->Trajectory{ //(p0,v0,a0,t0) //(p1,v1,a1,t1) - VirtualBody{ - body0, - body1:self, - } + Trajectory::new( + self.extrapolated_position(time)-trj0.extrapolated_position(time), + self.extrapolated_velocity(time)-trj0.extrapolated_velocity(time), + self.acceleration-trj0.acceleration, + time) } pub fn extrapolated_position(&self,time:Time)->Planar64Vec3{ let dt=time-self.time; @@ -144,28 +177,12 @@ impl Body } impl std::fmt::Display for Body{ + fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ + write!(f,"p({}) v({}) t({})",self.position,self.velocity,self.time) + } +} +impl std::fmt::Display for Trajectory{ fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{ write!(f,"p({}) v({}) a({}) t({})",self.position,self.velocity,self.acceleration,self.time) } } - -pub struct VirtualBody<'a,T>{ - body0:&'a Body, - body1:&'a Body, -} -impl VirtualBody<'_,T> - where Time:Copy, -{ - pub fn extrapolated_position(&self,time:Time)->Planar64Vec3{ - self.body1.extrapolated_position(time)-self.body0.extrapolated_position(time) - } - pub fn extrapolated_velocity(&self,time:Time)->Planar64Vec3{ - self.body1.extrapolated_velocity(time)-self.body0.extrapolated_velocity(time) - } - pub fn acceleration(&self)->Planar64Vec3{ - self.body1.acceleration-self.body0.acceleration - } - pub fn body(&self,time:Time)->Body{ - Body::new(self.extrapolated_position(time),self.extrapolated_velocity(time),self.acceleration(),time) - } -} -- 2.49.1 From b918772a00c9f9bafce185705600363fb99a2486 Mon Sep 17 00:00:00 2001 From: Rhys Lloyd Date: Tue, 27 Jan 2026 08:55:27 -0800 Subject: [PATCH 2/3] DELETE Body.acceleration --- engine/graphics/src/graphics.rs | 2 +- engine/physics/src/body.rs | 46 +++--- engine/physics/src/face_crawler.rs | 34 ++--- engine/physics/src/model.rs | 34 ++--- engine/physics/src/physics.rs | 194 +++++++++++-------------- engine/session/src/session.rs | 10 +- integration-testing/src/main.rs | 8 +- integration-testing/src/test_scenes.rs | 4 - integration-testing/src/tests.rs | 2 - 9 files changed, 151 insertions(+), 183 deletions(-) diff --git a/engine/graphics/src/graphics.rs b/engine/graphics/src/graphics.rs index dc1f9e16..90452239 100644 --- a/engine/graphics/src/graphics.rs +++ b/engine/graphics/src/graphics.rs @@ -909,7 +909,7 @@ impl GraphicsState{ // update rotation let camera_uniforms=self.camera.to_uniform_data( - frame_state.body.extrapolated_position(frame_state.time).map(Into::::into).to_array().into(), + frame_state.trajectory.extrapolated_position(frame_state.time).map(Into::::into).to_array().into(), frame_state.camera.simulate_move_angles(glam::IVec2::ZERO) ); self.staging_belt diff --git a/engine/physics/src/body.rs b/engine/physics/src/body.rs index eb4534d1..4f676805 100644 --- a/engine/physics/src/body.rs +++ b/engine/physics/src/body.rs @@ -47,6 +47,19 @@ impl Body time, } } + pub const fn with_acceleration(self,acceleration:Planar64Vec3)->Trajectory{ + let Body{ + position, + velocity, + time, + }=self; + Trajectory{ + position, + velocity, + acceleration, + time, + } + } } impl Trajectory @@ -61,19 +74,6 @@ impl Trajectory time, } } - pub const fn body_with_acceleration(body:Body,acceleration:Planar64Vec3)->Trajectory{ - let Body{ - position, - velocity, - time, - }=body; - Self{ - position, - velocity, - acceleration, - time, - } - } pub fn relative_to(&self,trj0:&Trajectory,time:Time)->Trajectory{ //(p0,v0,a0,t0) //(p1,v1,a1,t1) @@ -93,10 +93,12 @@ impl Trajectory let dt=time-self.time; self.velocity+(self.acceleration*dt).map(|elem|elem.divide().clamp_1()) } - pub fn advance_time(&mut self,time:Time){ - self.position=self.extrapolated_position(time); - self.velocity=self.extrapolated_velocity(time); - self.time=time; + pub fn extrapolated_body(&self,time:Time)->Body{ + Body::new( + self.extrapolated_position(time), + self.extrapolated_velocity(time), + time, + ) } pub fn extrapolated_position_ratio_dt(&self,dt:integer::Ratio)->Planar64Vec3 where @@ -134,10 +136,12 @@ impl Trajectory // a*dt + v 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); - self.velocity=self.extrapolated_velocity_ratio_dt(dt); - self.time+=dt.into(); + pub fn extrapolated_body_ratio_dt(&self,dt:crate::model::GigaTime)->Body{ + Body::new( + self.extrapolated_position_ratio_dt(dt), + self.extrapolated_velocity_ratio_dt(dt), + self.time+dt.into(), + ) } pub fn infinity_dir(&self)->Option{ if self.velocity==vec3::zero(){ diff --git a/engine/physics/src/face_crawler.rs b/engine/physics/src/face_crawler.rs index 44cfb914..3cc3e1cf 100644 --- a/engine/physics/src/face_crawler.rs +++ b/engine/physics/src/face_crawler.rs @@ -1,6 +1,6 @@ use crate::model::{into_giga_time,GigaTime,FEV,MeshQuery,DirectedEdge}; use strafesnet_common::integer::{Fixed,Ratio,vec3::Vector3}; -use crate::physics::{Time,Body}; +use crate::physics::{Time,Trajectory}; use core::ops::Bound; @@ -74,7 +74,7 @@ impl,Offset=Fixed<4,128>>> FEV >>::Output:core::iter::Sum, M::Offset:core::ops::Sub<>>::Output>, { - fn next_transition(&self,mesh:&M,body:&Body,lower_bound:Bound,mut upper_bound:Bound)->Transition{ + fn next_transition(&self,mesh:&M,trajectory:&Trajectory,lower_bound:Bound,mut upper_bound:Bound)->Transition{ //conflicting derivative means it crosses in the wrong direction. //if the transition time is equal to an already tested transition, do not replace the current best. let mut best_transition=Transition::Miss; @@ -86,8 +86,8 @@ impl,Offset=Fixed<4,128>>> FEV let (n,d)=mesh.face_nd(face_id); //TODO: use higher precision d value? //use the mesh transform translation instead of baking it into the d value. - for dt in Fixed::<4,128>::zeroes2((n.dot(body.position)-d)*2,n.dot(body.velocity)*2,n.dot(body.acceleration)){ - if low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ + for dt in Fixed::<4,128>::zeroes2((n.dot(trajectory.position)-d)*2,n.dot(trajectory.velocity)*2,n.dot(trajectory.acceleration)){ + if low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(trajectory.extrapolated_velocity_ratio_dt(dt)).is_negative(){ upper_bound=Bound::Included(dt); best_transition=Transition::Hit(face_id,dt); break; @@ -101,8 +101,8 @@ impl,Offset=Fixed<4,128>>> FEV //WARNING: d is moved out of the *2 block because of adding two vertices! //WARNING: precision is swept under the rug! //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 low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ + for dt in Fixed::<4,128>::zeroes2(n.dot(trajectory.position*2-(mesh.vert(v0)+mesh.vert(v1))).wrap_4(),n.dot(trajectory.velocity).wrap_4()*2,n.dot(trajectory.acceleration).wrap_4()){ + if low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(trajectory.extrapolated_velocity_ratio_dt(dt)).is_negative(){ upper_bound=Bound::Included(dt); best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt); break; @@ -117,15 +117,15 @@ impl,Offset=Fixed<4,128>>> FEV let &[ev0,ev1]=edge_verts.as_ref(); let (v0,v1)=(mesh.vert(ev0),mesh.vert(ev1)); let edge_n=v1-v0; - let delta_pos=body.position*2-(v0+v1); + let delta_pos=trajectory.position*2-(v0+v1); for (i,&edge_face_id) in mesh.edge_faces(edge_id).as_ref().iter().enumerate(){ let face_n=mesh.face_nd(edge_face_id).0; //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 //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 low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ + for dt in Fixed::<4,128>::zeroes2(n.dot(delta_pos).wrap_4(),n.dot(trajectory.velocity).wrap_4()*2,n.dot(trajectory.acceleration).wrap_4()){ + if low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(trajectory.extrapolated_velocity_ratio_dt(dt)).is_negative(){ upper_bound=Bound::Included(dt); best_transition=Transition::Next(FEV::Face(edge_face_id),dt); break; @@ -136,8 +136,8 @@ impl,Offset=Fixed<4,128>>> FEV for (i,&vert_id) in edge_verts.as_ref().iter().enumerate(){ //vertex normal gets parity from vert index 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 low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ + for dt in Fixed::<2,64>::zeroes2((n.dot(trajectory.position-mesh.vert(vert_id)))*2,n.dot(trajectory.velocity)*2,n.dot(trajectory.acceleration)){ + if low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(trajectory.extrapolated_velocity_ratio_dt(dt)).is_negative(){ let dt=Ratio::new(dt.num.widen_4(),dt.den.widen_4()); upper_bound=Bound::Included(dt); best_transition=Transition::Next(FEV::Vert(vert_id),dt); @@ -152,8 +152,8 @@ impl,Offset=Fixed<4,128>>> FEV for &directed_edge_id in mesh.vert_edges(vert_id).as_ref(){ //edge is directed away from vertex, but we want the dot product to turn out negative 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 low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(body.extrapolated_velocity_ratio_dt(dt)).is_negative(){ + for dt in Fixed::<2,64>::zeroes2((n.dot(trajectory.position-mesh.vert(vert_id)))*2,n.dot(trajectory.velocity)*2,n.dot(trajectory.acceleration)){ + if low(&lower_bound,&dt)&&upp(&dt,&upper_bound)&&n.dot(trajectory.extrapolated_velocity_ratio_dt(dt)).is_negative(){ let dt=Ratio::new(dt.num.widen_4(),dt.den.widen_4()); upper_bound=Bound::Included(dt); best_transition=Transition::Next(FEV::Edge(directed_edge_id.as_undirected()),dt); @@ -166,11 +166,11 @@ impl,Offset=Fixed<4,128>>> FEV } best_transition } - pub fn crawl(mut self,mesh:&M,relative_body:&Body,lower_bound:Bound<&Time>,upper_bound:Bound<&Time>)->CrawlResult{ - let mut lower_bound=lower_bound.map(|&t|into_giga_time(t,relative_body.time)); - let upper_bound=upper_bound.map(|&t|into_giga_time(t,relative_body.time)); + pub fn crawl(mut self,mesh:&M,trajectory:&Trajectory,lower_bound:Bound<&Time>,upper_bound:Bound<&Time>)->CrawlResult{ + let mut lower_bound=lower_bound.map(|&t|into_giga_time(t,trajectory.time)); + let upper_bound=upper_bound.map(|&t|into_giga_time(t,trajectory.time)); for _ in 0..20{ - match self.next_transition(mesh,relative_body,lower_bound,upper_bound){ + match self.next_transition(mesh,trajectory,lower_bound,upper_bound){ Transition::Miss=>return CrawlResult::Miss(self), Transition::Next(next_fev,next_time)=>(self,lower_bound)=(next_fev,Bound::Included(next_time)), Transition::Hit(face,time)=>return CrawlResult::Hit(face,time), diff --git a/engine/physics/src/model.rs b/engine/physics/src/model.rs index 57dc0618..4809fbcf 100644 --- a/engine/physics/src/model.rs +++ b/engine/physics/src/model.rs @@ -5,7 +5,7 @@ use strafesnet_common::model::{self,MeshId,PolygonIter}; use strafesnet_common::integer::{self,vec3,Fixed,Planar64,Planar64Vec3,Ratio}; use strafesnet_common::physics::Time; -type Body=crate::body::Body; +type Trajectory=crate::body::Trajectory; struct AsRefHelper(T); impl AsRef for AsRefHelper{ @@ -670,40 +670,40 @@ impl MinkowskiMesh<'_>{ mesh1, } } - pub fn predict_collision_in(&self,relative_body:&Body,range:impl RangeBounds