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,
}
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> {
type Storage = IdvStorage<Self>;
}
// 0 is pure physics, 1 is pure extrapolation
const PHYSICS_VS_EXTRAPOLATION_FACTOR: f32 = 0.2;
impl InterpolatableComponent for Pos {
type InterpData = InterpBuffer<Pos>;
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())
}
}

View File

@ -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));