veloren_voxygen_anim/quadruped_low/
run.rs

1use common::comp::body::parts::HeadState;
2
3use super::{
4    super::{Animation, vek::*},
5    QuadrupedLowSkeleton, SkeletonAttr,
6};
7use std::f32::consts::PI;
8
9pub struct RunAnimation;
10
11impl Animation for RunAnimation {
12    type Dependency<'a> = (
13        f32,
14        Vec3<f32>,
15        Vec3<f32>,
16        f32,
17        Vec3<f32>,
18        f32,
19        [HeadState; 3],
20    );
21    type Skeleton = QuadrupedLowSkeleton;
22
23    #[cfg(feature = "use-dyn-lib")]
24    const UPDATE_FN: &'static [u8] = b"quadruped_low_run\0";
25
26    #[cfg_attr(feature = "be-dyn-lib", export_name = "quadruped_low_run")]
27    fn update_skeleton_inner(
28        skeleton: &Self::Skeleton,
29        (velocity, orientation, last_ori, _global_time, avg_vel, acc_vel, head_states): Self::Dependency<'_>,
30        anim_time: f32,
31        _rate: &mut f32,
32        s_a: &SkeletonAttr,
33    ) -> Self::Skeleton {
34        let mut next = (*skeleton).clone();
35        let speed = (Vec2::<f32>::from(velocity).magnitude()).min(15.0);
36
37        let speednorm = (speed / 15.0).powf(0.25);
38        let mixed_vel = acc_vel + anim_time * 6.0; //sets run frequency using speed, with anim_time setting a floor
39
40        let lab: f32 = 0.8 * s_a.tempo;
41        let x_tilt = avg_vel.z.atan2(avg_vel.xy().magnitude()).max(-0.7) * speednorm;
42
43        let short = ((1.0 / (0.72 + 0.28 * ((mixed_vel * lab + PI * 0.25).sin()).powi(2))).sqrt())
44            * ((mixed_vel * lab + PI * 0.25).sin())
45            * speednorm;
46        let shortalt = (mixed_vel * lab + PI * 0.25).sin();
47
48        let foothoril = ((1.0 / (0.4 + (0.6) * ((mixed_vel * lab + PI * 1.45).sin()).powi(2)))
49            .sqrt())
50            * ((mixed_vel * lab + PI * 1.45).sin())
51            * speednorm;
52        let footvertl = (mixed_vel * lab + PI * 0.0).sin() * speednorm;
53
54        let foothorir = ((1.0 / (0.4 + (0.6) * ((mixed_vel * lab + PI * 0.45).sin()).powi(2)))
55            .sqrt())
56            * ((mixed_vel * lab + PI * 0.45).sin())
57            * speednorm;
58        let footvertr = (mixed_vel * lab + PI).sin() * speednorm;
59
60        //back feet
61        let foothorilb = ((1.0 / (0.4 + (0.6) * ((mixed_vel * lab + PI * 1.05).sin()).powi(2)))
62            .sqrt())
63            * ((mixed_vel * lab + PI * 1.05).sin())
64            * speednorm;
65        let footvertlb = (mixed_vel * lab + PI * (-0.4)).sin() * speednorm;
66
67        let foothorirb = ((1.0 / (0.4 + (0.6) * ((mixed_vel * lab + PI * 0.05).sin()).powi(2)))
68            .sqrt())
69            * ((mixed_vel * lab + PI * 0.05).sin())
70            * speednorm;
71        let footvertrb = (mixed_vel * lab + PI * 0.6).sin() * speednorm;
72
73        let ori: Vec2<f32> = Vec2::from(orientation);
74        let last_ori = Vec2::from(last_ori);
75        let tilt = if vek::Vec2::new(ori, last_ori)
76            .map(|o| o.magnitude_squared())
77            .map(|m| m > 0.001 && m.is_finite())
78            .reduce_and()
79            && ori.angle_between(last_ori).is_finite()
80        {
81            ori.angle_between(last_ori).min(0.2)
82                * last_ori.determine_side(Vec2::zero(), ori).signum()
83        } else {
84            0.0
85        } * 1.3;
86        next.tail_front.scale = Vec3::one() * 0.98;
87        next.tail_rear.scale = Vec3::one() * 0.98;
88
89        // Center head
90        next.jaw_c.scale = Vec3::one() * 0.98;
91        next.head_c_upper.position = Vec3::new(0.0, s_a.head_upper.0, s_a.head_upper.1);
92        next.head_c_upper.orientation = Quaternion::rotation_x(-s_a.lean.0 + x_tilt * -1.0)
93            * Quaternion::rotation_y(tilt * 0.3)
94            * Quaternion::rotation_z(short * -0.06 + tilt * -1.5);
95
96        next.head_c_lower.position = Vec3::new(0.0, s_a.head_lower.0, s_a.head_lower.1);
97        next.head_c_lower.orientation = Quaternion::rotation_y(tilt * 1.0)
98            * Quaternion::rotation_z(short * -0.15 + tilt * -0.8)
99            * Quaternion::rotation_x(x_tilt * 0.4);
100        next.head_c_lower.scale = Vec3::one() * (head_states[1].is_attached() as i32 as f32);
101
102        next.jaw_c.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
103
104        // Left head
105        next.jaw_l.scale = Vec3::one() * 0.98;
106        next.head_l_upper.position = Vec3::new(
107            -s_a.side_head_upper.0,
108            s_a.side_head_upper.1,
109            s_a.side_head_upper.2,
110        );
111        next.head_l_upper.orientation = Quaternion::rotation_x(-s_a.lean.0 + x_tilt * -1.0)
112            * Quaternion::rotation_y(tilt * 0.3)
113            * Quaternion::rotation_z(short * -0.06 + tilt * -1.5);
114
115        next.head_l_lower.position = Vec3::new(
116            -s_a.side_head_lower.0,
117            s_a.side_head_lower.1,
118            s_a.side_head_lower.2,
119        );
120        next.head_l_lower.orientation = Quaternion::rotation_y(tilt * 1.0)
121            * Quaternion::rotation_z(short * -0.15 + tilt * -0.8)
122            * Quaternion::rotation_x(x_tilt * 0.4);
123        next.head_l_lower.scale = Vec3::one() * (head_states[0].is_attached() as i32 as f32);
124
125        next.jaw_l.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
126
127        // Right head
128        next.jaw_r.scale = Vec3::one() * 0.98;
129        next.head_r_upper.position = Vec3::new(
130            s_a.side_head_upper.0,
131            s_a.side_head_upper.1,
132            s_a.side_head_upper.2,
133        );
134        next.head_r_upper.orientation = Quaternion::rotation_x(-s_a.lean.0 + x_tilt * -1.0)
135            * Quaternion::rotation_y(tilt * 0.3)
136            * Quaternion::rotation_z(short * -0.06 + tilt * -1.5);
137
138        next.head_r_lower.position = Vec3::new(
139            s_a.side_head_lower.0,
140            s_a.side_head_lower.1,
141            s_a.side_head_lower.2,
142        );
143        next.head_r_lower.orientation = Quaternion::rotation_y(tilt * 1.0)
144            * Quaternion::rotation_z(short * -0.15 + tilt * -0.8)
145            * Quaternion::rotation_x(x_tilt * 0.4);
146        next.head_r_lower.scale = Vec3::one() * (head_states[2].is_attached() as i32 as f32);
147
148        next.jaw_r.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
149
150        if s_a.tongue_for_tail {
151            next.tail_front.position = Vec3::new(0.0, s_a.tail_front.0, s_a.tail_front.1);
152            next.tail_rear.position = Vec3::new(0.0, s_a.tail_rear.0, s_a.tail_rear.1);
153        } else {
154            next.tail_front.position = Vec3::new(
155                0.0,
156                s_a.tail_front.0 + s_a.lean.0 * 2.0,
157                s_a.tail_front.1 + s_a.lean.0 * 2.0,
158            );
159            next.tail_front.orientation =
160                Quaternion::rotation_z(shortalt * -0.18 * s_a.lean.1 + tilt * 1.8)
161                    * Quaternion::rotation_y(shortalt * -0.1)
162                    * Quaternion::rotation_x(0.06 - s_a.lean.0 * 1.2 + x_tilt * 0.2);
163
164            next.tail_rear.position = Vec3::new(0.0, s_a.tail_rear.0, s_a.tail_rear.1);
165            next.tail_rear.orientation =
166                Quaternion::rotation_z(shortalt * -0.25 * s_a.lean.1 + tilt * 1.6)
167                    * Quaternion::rotation_y(shortalt * 0.08)
168                    * Quaternion::rotation_x(-0.04 + x_tilt * 0.5);
169        }
170        next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1);
171        next.chest.orientation = Quaternion::rotation_z(short * 0.13 + tilt * -1.9)
172            * Quaternion::rotation_y(short * 0.12 + tilt * 0.7)
173            * Quaternion::rotation_x(x_tilt + s_a.lean.0);
174
175        next.foot_fl.position = Vec3::new(
176            -s_a.feet_f.0,
177            s_a.feet_f.1 + foothoril * -2.0,
178            s_a.feet_f.2 + 1.0 * speednorm + ((footvertl * -1.8).max(-0.0)),
179        );
180        next.foot_fl.orientation =
181            Quaternion::rotation_x(-0.2 * speednorm + footvertl * -0.45 * s_a.lean.1 - s_a.lean.0)
182                * Quaternion::rotation_y(tilt * -1.0)
183                * Quaternion::rotation_z(foothoril * 0.4 * s_a.lean.1 + tilt * -2.0);
184
185        next.foot_fr.position = Vec3::new(
186            s_a.feet_f.0,
187            s_a.feet_f.1 + foothorir * -2.0,
188            s_a.feet_f.2 + 1.0 * speednorm + ((footvertr * -1.8).max(-0.0)),
189        );
190        next.foot_fr.orientation =
191            Quaternion::rotation_x(-0.2 * speednorm + footvertr * -0.45 * s_a.lean.1 - s_a.lean.0)
192                * Quaternion::rotation_y(tilt * -1.0)
193                * Quaternion::rotation_z(foothorir * -0.4 * s_a.lean.1 + tilt * -2.0);
194
195        next.foot_bl.position = Vec3::new(
196            -s_a.feet_b.0,
197            s_a.feet_b.1 + foothorilb * -1.0,
198            s_a.feet_b.2 + ((footvertlb * -1.2).max(-0.0)),
199        );
200        next.foot_bl.orientation =
201            Quaternion::rotation_x(-0.2 * speednorm + footvertlb * -0.5 - s_a.lean.0)
202                * Quaternion::rotation_y(tilt * -1.0)
203                * Quaternion::rotation_z(foothorilb * 0.4 + tilt * -2.0);
204
205        next.foot_br.position = Vec3::new(
206            s_a.feet_b.0,
207            s_a.feet_b.1 + foothorirb * -1.0,
208            s_a.feet_b.2 + ((footvertrb * -1.2).max(-0.0)),
209        );
210        next.foot_br.orientation =
211            Quaternion::rotation_x(-0.2 * speednorm + footvertrb * -0.5 - s_a.lean.0)
212                * Quaternion::rotation_y(tilt * -1.0)
213                * Quaternion::rotation_z(foothorirb * -0.4 + tilt * -2.0);
214
215        next
216    }
217}