diff --git a/common/net/src/sync/interpolation.rs b/common/net/src/sync/interpolation.rs index 17b9d4ef1c..b5ffec772a 100644 --- a/common/net/src/sync/interpolation.rs +++ b/common/net/src/sync/interpolation.rs @@ -14,22 +14,31 @@ pub struct InterpBuffer { pub i: usize, } +impl InterpBuffer { + fn push(&mut self, time: f64, x: T) { + let InterpBuffer { + ref mut buf, + ref mut i, + } = self; + *i += 1; + *i %= buf.len(); + buf[*i] = (time, x); + } +} + impl Component for InterpBuffer { type Storage = IdvStorage; } +// 0 is pure physics, 1 is pure extrapolation +const PHYSICS_VS_EXTRAPOLATION_FACTOR: f32 = 0.2; + impl InterpolatableComponent for Pos { type InterpData = InterpBuffer; type ReadData = Vel; fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) { - let InterpBuffer { - ref mut buf, - ref mut i, - } = interp_data; - *i += 1; - *i %= buf.len(); - buf[*i] = (time, *self); + interp_data.push(time, *self); } fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _vel: &Vel) -> Self { @@ -50,7 +59,7 @@ impl InterpolatableComponent for Pos { out = p1.0; } - Pos(out) + Pos(Lerp::lerp(self.0, out, PHYSICS_VS_EXTRAPOLATION_FACTOR)) } } @@ -59,13 +68,7 @@ impl InterpolatableComponent for Vel { type ReadData = (); fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) { - let InterpBuffer { - ref mut buf, - ref mut i, - } = interp_data; - *i += 1; - *i %= buf.len(); - buf[*i] = (time, *self); + interp_data.push(time, *self); } fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _: &()) -> Self { @@ -85,7 +88,7 @@ impl InterpolatableComponent for Vel { out = p1.0; } - Vel(out) + Vel(Lerp::lerp(self.0, out, PHYSICS_VS_EXTRAPOLATION_FACTOR)) } } @@ -94,13 +97,7 @@ impl InterpolatableComponent for Ori { type ReadData = (); fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) { - let InterpBuffer { - ref mut buf, - ref mut i, - } = interp_data; - *i += 1; - *i %= buf.len(); - buf[*i] = (time, *self); + interp_data.push(time, *self); } fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _: &()) -> Self { @@ -120,6 +117,6 @@ impl InterpolatableComponent for Ori { out = p1.0; } - Ori(out.normalized()) + Ori(Slerp::slerp(self.0, out, PHYSICS_VS_EXTRAPOLATION_FACTOR).normalized()) } } diff --git a/server/src/sys/entity_sync.rs b/server/src/sys/entity_sync.rs index 25fa256b45..c08e2874ea 100644 --- a/server/src/sys/entity_sync.rs +++ b/server/src/sys/entity_sync.rs @@ -249,9 +249,18 @@ impl<'a> System<'a> for Sys { { let mut comp_sync_package = CompSyncPackage::new(); let mut throttle = true; + + // extrapolation depends on receiving several frames indicating that something + // has stopped in order for the extrapolated value to have + // stopped + const SEND_UNCHANGED_PHYSICS_DATA: bool = true; + // TODO: An entity that stopped moving on a tick that it wasn't sent to the // player will never have its position updated - match last_pos.get(entity).map(|&l| l.0 != pos) { + match last_pos + .get(entity) + .map(|&l| l.0 != pos || SEND_UNCHANGED_PHYSICS_DATA) + { Some(false) => {}, Some(true) => { let _ = last_pos.insert(entity, Last(pos)); @@ -265,7 +274,10 @@ impl<'a> System<'a> for Sys { } if let Some(&vel) = maybe_vel { - match last_vel.get(entity).map(|&l| l.0 != vel) { + match last_vel + .get(entity) + .map(|&l| l.0 != vel || SEND_UNCHANGED_PHYSICS_DATA) + { Some(false) => {}, Some(true) => { let _ = last_vel.insert(entity, Last(vel)); @@ -286,7 +298,10 @@ impl<'a> System<'a> for Sys { } if let Some(&ori) = maybe_ori { - match last_ori.get(entity).map(|&l| l.0 != ori) { + match last_ori + .get(entity) + .map(|&l| l.0 != ori || SEND_UNCHANGED_PHYSICS_DATA) + { Some(false) => {}, Some(true) => { let _ = last_ori.insert(entity, Last(ori));