diff --git a/voxygen/src/scene/particle.rs b/voxygen/src/scene/particle.rs
index 44480fd300..29ae3be672 100644
--- a/voxygen/src/scene/particle.rs
+++ b/voxygen/src/scene/particle.rs
@@ -1,5 +1,6 @@
 use super::{terrain::BlocksOfInterest, SceneData, Terrain};
 use crate::{
+    ecs::comp::Interpolated,
     mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_particle},
     render::{
         pipelines::particle::ParticleMode, Instances, Light, Model, ParticleDrawer,
@@ -11,7 +12,7 @@ use common::{
     assets::{AssetExt, DotVoxAsset},
     comp::{
         self, aura, beam, body, buff, item::Reagent, object, shockwave, BeamSegment, Body,
-        CharacterState, Ori, Pos, Shockwave, Vel,
+        CharacterState, Shockwave, Vel,
     },
     figure::Segment,
     outcome::Outcome,
@@ -347,28 +348,28 @@ impl ParticleMgr {
             "ParticleMgr::maintain_body_particles"
         );
         let ecs = scene_data.state.ecs();
-        for (body, pos, vel) in (
+        for (body, interpolated, vel) in (
             &ecs.read_storage::<Body>(),
-            &ecs.read_storage::<Pos>(),
+            &ecs.read_storage::<Interpolated>(),
             ecs.read_storage::<Vel>().maybe(),
         )
             .join()
         {
             match body {
                 Body::Object(object::Body::CampfireLit) => {
-                    self.maintain_campfirelit_particles(scene_data, pos, vel)
+                    self.maintain_campfirelit_particles(scene_data, interpolated.pos, vel)
                 },
                 Body::Object(object::Body::BoltFire) => {
-                    self.maintain_boltfire_particles(scene_data, pos, vel)
+                    self.maintain_boltfire_particles(scene_data, interpolated.pos, vel)
                 },
                 Body::Object(object::Body::BoltFireBig) => {
-                    self.maintain_boltfirebig_particles(scene_data, pos, vel)
+                    self.maintain_boltfirebig_particles(scene_data, interpolated.pos, vel)
                 },
                 Body::Object(object::Body::BoltNature) => {
-                    self.maintain_boltnature_particles(scene_data, pos, vel)
+                    self.maintain_boltnature_particles(scene_data, interpolated.pos, vel)
                 },
                 Body::Object(object::Body::Tornado) => {
-                    self.maintain_tornado_particles(scene_data, pos)
+                    self.maintain_tornado_particles(scene_data, interpolated.pos)
                 },
                 Body::Object(
                     object::Body::Bomb
@@ -378,7 +379,7 @@ impl ParticleMgr {
                     | object::Body::FireworkRed
                     | object::Body::FireworkWhite
                     | object::Body::FireworkYellow,
-                ) => self.maintain_bomb_particles(scene_data, pos, vel),
+                ) => self.maintain_bomb_particles(scene_data, interpolated.pos, vel),
                 _ => {},
             }
         }
@@ -387,7 +388,7 @@ impl ParticleMgr {
     fn maintain_campfirelit_particles(
         &mut self,
         scene_data: &SceneData,
-        pos: &Pos,
+        pos: Vec3<f32>,
         vel: Option<&Vel>,
     ) {
         span!(
@@ -404,14 +405,14 @@ impl ParticleMgr {
                 Duration::from_millis(250),
                 time,
                 ParticleMode::CampfireFire,
-                pos.0,
+                pos,
             ));
 
             self.particles.push(Particle::new(
                 Duration::from_secs(10),
                 time,
                 ParticleMode::CampfireSmoke,
-                pos.0.map(|e| e + thread_rng().gen_range(-0.25..0.25))
+                pos.map(|e| e + thread_rng().gen_range(-0.25..0.25))
                     + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
             ));
         }
@@ -420,7 +421,7 @@ impl ParticleMgr {
     fn maintain_boltfire_particles(
         &mut self,
         scene_data: &SceneData,
-        pos: &Pos,
+        pos: Vec3<f32>,
         vel: Option<&Vel>,
     ) {
         span!(
@@ -437,13 +438,13 @@ impl ParticleMgr {
                 Duration::from_millis(500),
                 time,
                 ParticleMode::CampfireFire,
-                pos.0,
+                pos,
             ));
             self.particles.push(Particle::new(
                 Duration::from_secs(1),
                 time,
                 ParticleMode::CampfireSmoke,
-                pos.0.map(|e| e + rng.gen_range(-0.25..0.25))
+                pos.map(|e| e + rng.gen_range(-0.25..0.25))
                     + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
             ));
         }
@@ -452,7 +453,7 @@ impl ParticleMgr {
     fn maintain_boltfirebig_particles(
         &mut self,
         scene_data: &SceneData,
-        pos: &Pos,
+        pos: Vec3<f32>,
         vel: Option<&Vel>,
     ) {
         span!(
@@ -472,7 +473,7 @@ impl ParticleMgr {
                     Duration::from_millis(500),
                     time,
                     ParticleMode::CampfireFire,
-                    pos.0.map(|e| e + rng.gen_range(-0.25..0.25))
+                    pos.map(|e| e + rng.gen_range(-0.25..0.25))
                         + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
                 )
             },
@@ -486,7 +487,7 @@ impl ParticleMgr {
                     Duration::from_secs(2),
                     time,
                     ParticleMode::CampfireSmoke,
-                    pos.0.map(|e| e + rng.gen_range(-0.25..0.25))
+                    pos.map(|e| e + rng.gen_range(-0.25..0.25))
                         + vel.map_or(Vec3::zero(), |v| -v.0 * dt),
                 )
             },
@@ -496,7 +497,7 @@ impl ParticleMgr {
     fn maintain_boltnature_particles(
         &mut self,
         scene_data: &SceneData,
-        pos: &Pos,
+        pos: Vec3<f32>,
         vel: Option<&Vel>,
     ) {
         let time = scene_data.state.get_time();
@@ -511,14 +512,14 @@ impl ParticleMgr {
                     Duration::from_millis(500),
                     time,
                     ParticleMode::CampfireSmoke,
-                    pos.0.map(|e| e + rng.gen_range(-0.25..0.25))
+                    pos.map(|e| e + rng.gen_range(-0.25..0.25))
                         + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
                 )
             },
         );
     }
 
-    fn maintain_tornado_particles(&mut self, scene_data: &SceneData, pos: &Pos) {
+    fn maintain_tornado_particles(&mut self, scene_data: &SceneData, pos: Vec3<f32>) {
         let time = scene_data.state.get_time();
         let mut rng = thread_rng();
 
@@ -530,13 +531,18 @@ impl ParticleMgr {
                     Duration::from_millis(1000),
                     time,
                     ParticleMode::Tornado,
-                    pos.0.map(|e| e + rng.gen_range(-0.25..0.25)),
+                    pos.map(|e| e + rng.gen_range(-0.25..0.25)),
                 )
             },
         );
     }
 
-    fn maintain_bomb_particles(&mut self, scene_data: &SceneData, pos: &Pos, vel: Option<&Vel>) {
+    fn maintain_bomb_particles(
+        &mut self,
+        scene_data: &SceneData,
+        pos: Vec3<f32>,
+        vel: Option<&Vel>,
+    ) {
         span!(
             _guard,
             "bomb_particles",
@@ -552,7 +558,7 @@ impl ParticleMgr {
                 Duration::from_millis(1500),
                 time,
                 ParticleMode::GunPowderSpark,
-                pos.0,
+                pos,
             ));
 
             // smoke
@@ -560,7 +566,7 @@ impl ParticleMgr {
                 Duration::from_secs(2),
                 time,
                 ParticleMode::CampfireSmoke,
-                pos.0 + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
+                pos + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
             ));
         }
     }
@@ -577,9 +583,9 @@ impl ParticleMgr {
         let dt = scene_data.state.get_delta_time();
         let mut rng = thread_rng();
 
-        for (entity, pos, vel, character_state, body) in (
+        for (entity, interpolated, vel, character_state, body) in (
             &ecs.entities(),
-            &ecs.read_storage::<Pos>(),
+            &ecs.read_storage::<Interpolated>(),
             ecs.read_storage::<Vel>().maybe(),
             &ecs.read_storage::<CharacterState>(),
             &ecs.read_storage::<Body>(),
@@ -596,7 +602,8 @@ impl ParticleMgr {
                                 Duration::from_secs(15),
                                 time,
                                 ParticleMode::CampfireSmoke,
-                                pos.0 + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
+                                interpolated.pos
+                                    + vel.map_or(Vec3::zero(), |v| -v.0 * dt * rng.gen::<f32>()),
                             )
                         },
                     );
@@ -624,28 +631,30 @@ impl ParticleMgr {
                                             )
                                             .normalized()
                                                 * rand_dist
-                                                + pos.0
+                                                + interpolated.pos
                                                 + Vec3::unit_z() * 0.05;
                                             Particle::new_directed(
                                                 Duration::from_millis(900),
                                                 time,
                                                 ParticleMode::CultistFlame,
                                                 init_pos,
-                                                pos.0,
+                                                interpolated.pos,
                                             )
                                         },
                                     );
                                     // Particles for lifesteal effect
-                                    for (_entity_b, pos_b, body_b, _health_b) in (
+                                    for (_entity_b, interpolated_b, body_b, _health_b) in (
                                         &ecs.entities(),
-                                        &ecs.read_storage::<Pos>(),
+                                        &ecs.read_storage::<Interpolated>(),
                                         &ecs.read_storage::<Body>(),
                                         &ecs.read_storage::<comp::Health>(),
                                     )
                                         .join()
                                         .filter(|(e, _, _, h)| !h.is_dead && entity != *e)
                                     {
-                                        if pos.0.distance_squared(pos_b.0) < range.powi(2) {
+                                        if interpolated.pos.distance_squared(interpolated_b.pos)
+                                            < range.powi(2)
+                                        {
                                             let heartbeats = self
                                                 .scheduler
                                                 .heartbeats(Duration::from_millis(20));
@@ -655,7 +664,7 @@ impl ParticleMgr {
                                                         * usize::from(heartbeats)
                                                         / 150,
                                                 || {
-                                                    let start_pos = pos_b.0
+                                                    let start_pos = interpolated_b.pos
                                                         + Vec3::unit_z() * body_b.height() * 0.5
                                                         + Vec3::<f32>::zero()
                                                             .map(|_| rng.gen_range(-1.0..1.0))
@@ -666,7 +675,7 @@ impl ParticleMgr {
                                                         time,
                                                         ParticleMode::CultistFlame,
                                                         start_pos,
-                                                        pos.0
+                                                        interpolated.pos
                                                             + Vec3::unit_z() * body.height() * 0.5,
                                                     )
                                                 },
@@ -683,8 +692,9 @@ impl ParticleMgr {
                         self.particles.len()
                             + usize::from(self.scheduler.heartbeats(Duration::from_millis(10))),
                         || {
-                            let center_pos = pos.0 + Vec3::unit_z() * body.height() / 2.0;
-                            let outer_pos = pos.0
+                            let center_pos =
+                                interpolated.pos + Vec3::unit_z() * body.height() / 2.0;
+                            let outer_pos = interpolated.pos
                                 + Vec3::new(
                                     2.0 * rng.gen::<f32>() - 1.0,
                                     2.0 * rng.gen::<f32>() - 1.0,
@@ -721,14 +731,15 @@ impl ParticleMgr {
                                         self.scheduler.heartbeats(Duration::from_millis(5)),
                                     ),
                                 || {
-                                    let start_pos = pos.0
+                                    let start_pos = interpolated.pos
                                         + Vec3::new(
                                             body.max_radius(),
                                             body.max_radius(),
                                             body.height() / 2.0,
                                         )
                                         .map(|d| d * rng.gen_range(-1.0..1.0));
-                                    let end_pos = pos.0 + (start_pos - pos.0) * 6.0;
+                                    let end_pos =
+                                        interpolated.pos + (start_pos - interpolated.pos) * 6.0;
                                     Particle::new_directed(
                                         Duration::from_secs(1),
                                         time,
@@ -752,13 +763,12 @@ impl ParticleMgr {
         let time = state.get_time();
         let dt = scene_data.state.ecs().fetch::<DeltaTime>().0;
 
-        for (pos, ori, beam) in (
-            &ecs.read_storage::<Pos>(),
-            &ecs.read_storage::<Ori>(),
+        for (interpolated, beam) in (
+            &ecs.read_storage::<Interpolated>(),
             &ecs.read_storage::<BeamSegment>(),
         )
             .join()
-            .filter(|(_, _, b)| b.creation.map_or(true, |c| (c + dt as f64) >= time))
+            .filter(|(_, b)| b.creation.map_or(true, |c| (c + dt as f64) >= time))
         {
             // TODO: Handle this less hackily. Done this way as beam segments are created
             // every server tick, which is approximately 33 ms. Heartbeat scheduler used to
@@ -769,11 +779,11 @@ impl ParticleMgr {
             match beam.properties.specifier {
                 beam::FrontendSpecifier::Flamethrower => {
                     let mut rng = thread_rng();
-                    let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
+                    let (from, to) = (Vec3::<f32>::unit_z(), *interpolated.ori.look_dir());
                     let m = Mat3::<f32>::rotation_from_to_3d(from, to);
                     // Emit a light when using flames
                     lights.push(Light::new(
-                        pos.0,
+                        interpolated.pos,
                         Rgb::new(1.0, 0.25, 0.05).map(|e| e * rng.gen_range(0.8..1.2)),
                         2.0,
                     ));
@@ -792,19 +802,19 @@ impl ParticleMgr {
                                 beam.properties.duration,
                                 time,
                                 ParticleMode::FlameThrower,
-                                pos.0,
-                                pos.0 + random_ori * range,
+                                interpolated.pos,
+                                interpolated.pos + random_ori * range,
                             )
                         },
                     );
                 },
                 beam::FrontendSpecifier::Cultist => {
                     let mut rng = thread_rng();
-                    let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
+                    let (from, to) = (Vec3::<f32>::unit_z(), *interpolated.ori.look_dir());
                     let m = Mat3::<f32>::rotation_from_to_3d(from, to);
                     // Emit a light when using flames
                     lights.push(Light::new(
-                        pos.0,
+                        interpolated.pos,
                         Rgb::new(1.0, 0.0, 1.0).map(|e| e * rng.gen_range(0.5..1.0)),
                         2.0,
                     ));
@@ -823,23 +833,23 @@ impl ParticleMgr {
                                 beam.properties.duration,
                                 time,
                                 ParticleMode::CultistFlame,
-                                pos.0,
-                                pos.0 + random_ori * range,
+                                interpolated.pos,
+                                interpolated.pos + random_ori * range,
                             )
                         },
                     );
                 },
                 beam::FrontendSpecifier::LifestealBeam => {
                     // Emit a light when using lifesteal beam
-                    lights.push(Light::new(pos.0, Rgb::new(0.8, 1.0, 0.5), 1.0));
+                    lights.push(Light::new(interpolated.pos, Rgb::new(0.8, 1.0, 0.5), 1.0));
                     self.particles.reserve(beam_tick_count as usize);
                     for i in 0..beam_tick_count {
                         self.particles.push(Particle::new_directed(
                             beam.properties.duration,
                             time + i as f64 / 1000.0,
                             ParticleMode::LifestealBeam,
-                            pos.0,
-                            pos.0 + *ori.look_dir() * range,
+                            interpolated.pos,
+                            interpolated.pos + *interpolated.ori.look_dir() * range,
                         ));
                     }
                 },
@@ -849,8 +859,8 @@ impl ParticleMgr {
                             beam.properties.duration,
                             time,
                             ParticleMode::Laser,
-                            pos.0,
-                            pos.0 + *ori.look_dir() * range,
+                            interpolated.pos,
+                            interpolated.pos + *interpolated.ori.look_dir() * range,
                         )
                     })
                 },
@@ -860,14 +870,14 @@ impl ParticleMgr {
                             beam.properties.duration,
                             time,
                             ParticleMode::WebStrand,
-                            pos.0,
-                            pos.0 + *ori.look_dir() * range,
+                            interpolated.pos,
+                            interpolated.pos + *interpolated.ori.look_dir() * range,
                         )
                     })
                 },
                 beam::FrontendSpecifier::Bubbles => {
                     let mut rng = thread_rng();
-                    let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
+                    let (from, to) = (Vec3::<f32>::unit_z(), *interpolated.ori.look_dir());
                     let m = Mat3::<f32>::rotation_from_to_3d(from, to);
                     self.particles.resize_with(
                         self.particles.len() + usize::from(beam_tick_count) / 15,
@@ -884,15 +894,15 @@ impl ParticleMgr {
                                 beam.properties.duration,
                                 time,
                                 ParticleMode::Bubbles,
-                                pos.0,
-                                pos.0 + random_ori * range,
+                                interpolated.pos,
+                                interpolated.pos + random_ori * range,
                             )
                         },
                     );
                 },
                 beam::FrontendSpecifier::Frost => {
                     let mut rng = thread_rng();
-                    let (from, to) = (Vec3::<f32>::unit_z(), *ori.look_dir());
+                    let (from, to) = (Vec3::<f32>::unit_z(), *interpolated.ori.look_dir());
                     let m = Mat3::<f32>::rotation_from_to_3d(from, to);
                     self.particles.resize_with(
                         self.particles.len() + usize::from(beam_tick_count) / 4,
@@ -909,8 +919,8 @@ impl ParticleMgr {
                                 beam.properties.duration,
                                 time,
                                 ParticleMode::Ice,
-                                pos.0,
-                                pos.0 + random_ori * range,
+                                interpolated.pos,
+                                interpolated.pos + random_ori * range,
                             )
                         },
                     );
@@ -926,8 +936,8 @@ impl ParticleMgr {
         let mut rng = thread_rng();
         let dt = scene_data.state.get_delta_time();
 
-        for (pos, auras) in (
-            &ecs.read_storage::<Pos>(),
+        for (interpolated, auras) in (
+            &ecs.read_storage::<Interpolated>(),
             &ecs.read_storage::<comp::Auras>(),
         )
             .join()
@@ -950,8 +960,8 @@ impl ParticleMgr {
                                     aura.duration.map_or(max_dur, |dur| dur.min(max_dur)),
                                     time,
                                     ParticleMode::EnergyNature,
-                                    pos.0,
-                                    pos.0 + init_pos,
+                                    interpolated.pos,
+                                    interpolated.pos + init_pos,
                                 )
                             },
                         );
@@ -982,8 +992,8 @@ impl ParticleMgr {
                                     aura.duration.map_or(max_dur, |dur| dur.min(max_dur)),
                                     time,
                                     ParticleMode::EnergyHealing,
-                                    pos.0,
-                                    pos.0 + init_pos,
+                                    interpolated.pos,
+                                    interpolated.pos + init_pos,
                                 )
                             },
                         );
@@ -1006,15 +1016,15 @@ impl ParticleMgr {
                                     let radius = aura.radius * rng.gen::<f32>().sqrt();
                                     let x = radius * theta.sin();
                                     let y = radius * theta.cos();
-                                    Vec2::new(x, y) + pos.0.xy()
+                                    Vec2::new(x, y) + interpolated.pos.xy()
                                 };
                                 let max_dur = Duration::from_secs(1);
                                 Particle::new_directed(
                                     aura.duration.map_or(max_dur, |dur| dur.min(max_dur)),
                                     time,
                                     ParticleMode::FlameThrower,
-                                    rand_pos.with_z(pos.0.z),
-                                    rand_pos.with_z(pos.0.z + 1.0),
+                                    rand_pos.with_z(interpolated.pos.z),
+                                    rand_pos.with_z(interpolated.pos.z + 1.0),
                                 )
                             });
                     },
@@ -1034,8 +1044,8 @@ impl ParticleMgr {
                                     aura.duration.map_or(max_dur, |dur| dur.min(max_dur)),
                                     time,
                                     ParticleMode::EnergyBuffing,
-                                    pos.0,
-                                    pos.0 + init_pos,
+                                    interpolated.pos,
+                                    interpolated.pos + init_pos,
                                 )
                             },
                         );
@@ -1052,8 +1062,8 @@ impl ParticleMgr {
         let time = state.get_time();
         let mut rng = rand::thread_rng();
 
-        for (pos, buffs, body) in (
-            &ecs.read_storage::<Pos>(),
+        for (interpolated, buffs, body) in (
+            &ecs.read_storage::<Interpolated>(),
             &ecs.read_storage::<comp::Buffs>(),
             &ecs.read_storage::<comp::Body>(),
         )
@@ -1067,7 +1077,7 @@ impl ParticleMgr {
                             self.particles.len()
                                 + usize::from(self.scheduler.heartbeats(Duration::from_millis(15))),
                             || {
-                                let start_pos = pos.0
+                                let start_pos = interpolated.pos
                                     + Vec3::unit_z() * body.height() * 0.25
                                     + Vec3::<f32>::zero()
                                         .map(|_| rng.gen_range(-1.0..1.0))
@@ -1097,7 +1107,7 @@ impl ParticleMgr {
                             self.particles.len()
                                 + usize::from(self.scheduler.heartbeats(Duration::from_millis(15))),
                             || {
-                                let start_pos = pos.0
+                                let start_pos = interpolated.pos
                                     + Vec3::new(
                                         body.max_radius(),
                                         body.max_radius(),
@@ -1139,9 +1149,10 @@ impl ParticleMgr {
         let time = scene_data.state.get_time();
         let player_pos = scene_data
             .state
-            .read_component_copied::<Pos>(scene_data.player_entity)
+            .read_component_copied::<Interpolated>(scene_data.player_entity)
+            .map(|i| i.pos)
             .unwrap_or_default();
-        let player_chunk = player_pos.0.xy().map2(TerrainChunk::RECT_SIZE, |e, sz| {
+        let player_chunk = player_pos.xy().map2(TerrainChunk::RECT_SIZE, |e, sz| {
             (e.floor() as i32).div_euclid(sz as i32)
         });
 
@@ -1350,10 +1361,9 @@ impl ParticleMgr {
         let dt = scene_data.state.ecs().fetch::<DeltaTime>().0;
         let terrain = scene_data.state.ecs().fetch::<TerrainGrid>();
 
-        for (_entity, pos, ori, shockwave) in (
+        for (_entity, interpolated, shockwave) in (
             &ecs.entities(),
-            &ecs.read_storage::<Pos>(),
-            &ecs.read_storage::<Ori>(),
+            &ecs.read_storage::<Interpolated>(),
             &ecs.read_storage::<Shockwave>(),
         )
             .join()
@@ -1367,7 +1377,7 @@ impl ParticleMgr {
 
             let radians = shockwave.properties.angle.to_radians();
 
-            let ori_vec = ori.look_vec();
+            let ori_vec = interpolated.ori.look_vec();
             let theta = ori_vec.y.atan2(ori_vec.x) - radians / 2.0;
             let dtheta = radians / distance;
 
@@ -1396,7 +1406,7 @@ impl ParticleMgr {
                         for d in 0..(new_particle_count as i32) {
                             let arc_position = theta + dtheta * d as f32 / particle_count_factor;
 
-                            let position = pos.0
+                            let position = interpolated.pos
                                 + distance * Vec3::new(arc_position.cos(), arc_position.sin(), 0.0);
 
                             // Arbitrary number chosen that is large enough to be able to accurately
@@ -1446,7 +1456,7 @@ impl ParticleMgr {
                         for d in 0..3 * distance as i32 {
                             let arc_position = theta + dtheta * d as f32 / 3.0;
 
-                            let position = pos.0
+                            let position = interpolated.pos
                                 + distance * Vec3::new(arc_position.cos(), arc_position.sin(), 0.0);
 
                             self.particles.push(Particle::new(
@@ -1479,7 +1489,7 @@ impl ParticleMgr {
                             // Sub tick dt
                             let dt = (j as f32 / heartbeats as f32) * dt;
                             let distance = distance + speed * dt;
-                            let pos1 = pos.0 + distance * direction - Vec3::unit_z();
+                            let pos1 = interpolated.pos + distance * direction - Vec3::unit_z();
                             let pos2 = pos1 + (Vec3::unit_z() + direction) * 3.0;
                             let time = time + dt as f64;
 
@@ -1522,7 +1532,8 @@ impl ParticleMgr {
                             // Sub tick dt
                             let dt = (j as f32 / heartbeats as f32) * dt;
                             let scaled_distance = scaled_distance + scaled_speed * dt;
-                            let pos1 = pos.0 + (scaled_distance * direction).floor() * scale;
+                            let pos1 =
+                                interpolated.pos + (scaled_distance * direction).floor() * scale;
                             let time = time + dt as f64;
 
                             let get_positions = |a| {