veloren_voxygen_anim/quadruped_low/
run.rs1use 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; 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 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 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 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 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}