Add lerping of physics to extrapolated position, and enable sending updates for stopped entities.

This commit is contained in:
Avi Weinstock 2021-03-13 18:36:48 -05:00
parent dad0012973
commit bbb11882e2
2 changed files with 39 additions and 27 deletions

View File

@ -14,22 +14,31 @@ pub struct InterpBuffer<T> {
pub i: usize, pub i: usize,
} }
impl<T> InterpBuffer<T> {
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<T: 'static + Send + Sync> Component for InterpBuffer<T> { impl<T: 'static + Send + Sync> Component for InterpBuffer<T> {
type Storage = IdvStorage<Self>; type Storage = IdvStorage<Self>;
} }
// 0 is pure physics, 1 is pure extrapolation
const PHYSICS_VS_EXTRAPOLATION_FACTOR: f32 = 0.2;
impl InterpolatableComponent for Pos { impl InterpolatableComponent for Pos {
type InterpData = InterpBuffer<Pos>; type InterpData = InterpBuffer<Pos>;
type ReadData = Vel; type ReadData = Vel;
fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) { fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) {
let InterpBuffer { interp_data.push(time, *self);
ref mut buf,
ref mut i,
} = interp_data;
*i += 1;
*i %= buf.len();
buf[*i] = (time, *self);
} }
fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _vel: &Vel) -> Self { fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _vel: &Vel) -> Self {
@ -50,7 +59,7 @@ impl InterpolatableComponent for Pos {
out = p1.0; 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 = (); type ReadData = ();
fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) { fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) {
let InterpBuffer { interp_data.push(time, *self);
ref mut buf,
ref mut i,
} = interp_data;
*i += 1;
*i %= buf.len();
buf[*i] = (time, *self);
} }
fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _: &()) -> Self { fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _: &()) -> Self {
@ -85,7 +88,7 @@ impl InterpolatableComponent for Vel {
out = p1.0; 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 = (); type ReadData = ();
fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) { fn update_component(&self, interp_data: &mut Self::InterpData, time: f64) {
let InterpBuffer { interp_data.push(time, *self);
ref mut buf,
ref mut i,
} = interp_data;
*i += 1;
*i %= buf.len();
buf[*i] = (time, *self);
} }
fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _: &()) -> Self { fn interpolate(self, interp_data: &Self::InterpData, t2: f64, _: &()) -> Self {
@ -120,6 +117,6 @@ impl InterpolatableComponent for Ori {
out = p1.0; out = p1.0;
} }
Ori(out.normalized()) Ori(Slerp::slerp(self.0, out, PHYSICS_VS_EXTRAPOLATION_FACTOR).normalized())
} }
} }

View File

@ -249,9 +249,18 @@ impl<'a> System<'a> for Sys {
{ {
let mut comp_sync_package = CompSyncPackage::new(); let mut comp_sync_package = CompSyncPackage::new();
let mut throttle = true; 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 // TODO: An entity that stopped moving on a tick that it wasn't sent to the
// player will never have its position updated // 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(false) => {},
Some(true) => { Some(true) => {
let _ = last_pos.insert(entity, Last(pos)); let _ = last_pos.insert(entity, Last(pos));
@ -265,7 +274,10 @@ impl<'a> System<'a> for Sys {
} }
if let Some(&vel) = maybe_vel { 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(false) => {},
Some(true) => { Some(true) => {
let _ = last_vel.insert(entity, Last(vel)); let _ = last_vel.insert(entity, Last(vel));
@ -286,7 +298,10 @@ impl<'a> System<'a> for Sys {
} }
if let Some(&ori) = maybe_ori { 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(false) => {},
Some(true) => { Some(true) => {
let _ = last_ori.insert(entity, Last(ori)); let _ = last_ori.insert(entity, Last(ori));