veloren_voxygen/ecs/sys/
interpolation.rs1use crate::ecs::comp::Interpolated;
2use common::{
3 comp::{Body, Ori, Pos, Vel, object},
4 resources::DeltaTime,
5};
6use common_ecs::{Job, Origin, Phase, System};
7use specs::{Entities, Join, Read, ReadStorage, WriteStorage};
8use tracing::warn;
9use vek::*;
10
11#[derive(Default)]
13pub struct Sys;
14impl<'a> System<'a> for Sys {
15 type SystemData = (
16 Entities<'a>,
17 Read<'a, DeltaTime>,
18 ReadStorage<'a, Pos>,
19 ReadStorage<'a, Ori>,
20 ReadStorage<'a, Vel>,
21 ReadStorage<'a, Body>,
22 WriteStorage<'a, Interpolated>,
23 );
24
25 const NAME: &'static str = "interpolation";
26 const ORIGIN: Origin = Origin::Frontend("voxygen");
27 const PHASE: Phase = Phase::Create;
28
29 fn run(
30 _job: &mut Job<Self>,
31 (entities, dt, positions, orientations, velocities, bodies, mut interpolated): Self::SystemData,
32 ) {
33 for (pos, ori, i, body, vel) in (
35 &positions,
36 &orientations,
37 &mut interpolated,
38 &bodies,
39 &velocities,
40 )
41 .join()
42 {
43 if i.pos.distance_squared(pos.0) < 64.0 * 64.0 && !matches!(body, Body::Object(_)) {
45 const POS_LERP_RATE_FACTOR: f32 = 10.0;
49 i.pos = Lerp::lerp(i.pos, pos.0 + vel.0 * 0.03, POS_LERP_RATE_FACTOR * dt.0);
50 i.ori = Ori::slerp(i.ori, *ori, base_ori_interp(body) * dt.0);
51 } else {
52 i.pos = pos.0;
53 i.ori = *ori;
54 }
55 }
56 for (entity, pos, ori) in (&entities, &positions, &orientations, !&interpolated)
58 .join()
59 .map(|(e, p, o, _)| (e, p.0, *o))
60 .collect::<Vec<_>>()
61 {
62 interpolated
63 .insert(entity, Interpolated { pos, ori })
64 .err()
65 .map(|e| warn!(?e, "Error inserting Interpolated component"));
66 }
67 for entity in (&entities, !&positions, &interpolated)
70 .join()
71 .map(|(e, _, _)| e)
72 .collect::<Vec<_>>()
73 {
74 interpolated.remove(entity);
75 }
76 for entity in (&entities, !&orientations, &interpolated)
77 .join()
78 .map(|(e, _, _)| e)
79 .collect::<Vec<_>>()
80 {
81 interpolated.remove(entity);
82 }
83 for entity in (&entities, !&velocities, &interpolated)
84 .join()
85 .map(|(e, _, _)| e)
86 .collect::<Vec<_>>()
87 {
88 interpolated.remove(entity);
89 }
90 }
91}
92
93fn base_ori_interp(body: &Body) -> f32 {
94 match body {
95 Body::Object(
96 object::Body::Crossbow
97 | object::Body::Flamethrower
98 | object::Body::Lavathrower
99 | object::Body::HaniwaSentry
100 | object::Body::TerracottaStatue
101 | object::Body::MinotaurAxe,
102 ) => 100.0,
103 _ => 10.0,
104 }
105}