veloren_voxygen_anim/bird_large/
fly.rs

1use super::{
2    super::{Animation, vek::*},
3    BirdLargeSkeleton, SkeletonAttr,
4};
5
6pub struct FlyAnimation;
7
8impl Animation for FlyAnimation {
9    type Dependency<'a> = (Vec3<f32>, Vec3<f32>, Vec3<f32>);
10    type Skeleton = BirdLargeSkeleton;
11
12    #[cfg(feature = "use-dyn-lib")]
13    const UPDATE_FN: &'static [u8] = b"bird_large_fly\0";
14
15    #[cfg_attr(feature = "be-dyn-lib", export_name = "bird_large_fly")]
16    fn update_skeleton_inner(
17        skeleton: &Self::Skeleton,
18        (velocity, orientation, last_ori): Self::Dependency<'_>,
19        anim_time: f32,
20        _rate: &mut f32,
21        s_a: &SkeletonAttr,
22    ) -> Self::Skeleton {
23        let mut next = (*skeleton).clone();
24
25        let slow = (anim_time * 2.0).sin();
26        let fast = (anim_time * 4.0).sin();
27
28        // Harmonic series hack to get a sine/saw mix
29        let freq = if s_a.wyvern { 6.0 } else { 8.0 };
30        let off1 = 0.0;
31        let off2 = -1.7;
32        let off3 = -2.0;
33        let off4 = -2.4;
34        let flap1 = 7.0 / 16.0 * (freq * anim_time + off1).sin()
35            + 7.0 / 64.0 * (freq * 2.0 * anim_time + off1).sin()
36            + 1.0 / 48.0 * (freq * 3.0 * anim_time + off1).sin();
37        let flap2 = 7.0 / 16.0 * (freq * anim_time + off2).sin()
38            + 7.0 / 64.0 * (freq * 2.0 * anim_time + off2).sin()
39            + 1.0 / 48.0 * (freq * 3.0 * anim_time + off2).sin();
40        let flap3 = 7.0 / 16.0 * (freq * anim_time + off3).sin()
41            + 7.0 / 64.0 * (freq * 2.0 * anim_time + off3).sin()
42            + 1.0 / 48.0 * (freq * 3.0 * anim_time + off3).sin();
43        let flap4 = 7.0 / 16.0 * (freq * anim_time + off4).sin()
44            + 7.0 / 64.0 * (freq * 2.0 * anim_time + off4).sin()
45            + 1.0 / 48.0 * (freq * 3.0 * anim_time + off4).sin();
46
47        let ori: Vec2<f32> = Vec2::from(orientation);
48        let last_ori = Vec2::from(last_ori);
49        let tilt = if vek::Vec2::new(ori, last_ori)
50            .map(|o| o.magnitude_squared())
51            .map(|m| m > 0.001 && m.is_finite())
52            .reduce_and()
53            && ori.angle_between(last_ori).is_finite()
54        {
55            ori.angle_between(last_ori).min(0.2)
56                * last_ori.determine_side(Vec2::zero(), ori).signum()
57        } else {
58            0.0
59        } * 1.3;
60
61        next.head.scale = Vec3::one() * 0.99;
62        next.neck.scale = Vec3::one() * 1.01;
63        next.leg_l.scale = Vec3::one();
64        next.leg_r.scale = Vec3::one();
65        next.foot_l.scale = Vec3::one() * 1.01;
66        next.foot_r.scale = Vec3::one() * 1.01;
67        next.chest.scale = Vec3::one() * s_a.scaler * 0.99;
68        next.tail_front.scale = Vec3::one() * 1.01;
69        next.tail_rear.scale = Vec3::one() * 0.99;
70
71        next.neck.position = Vec3::new(0.0, s_a.neck.0, s_a.neck.1);
72        next.neck.orientation =
73            Quaternion::rotation_x((-0.4 + 0.2 * velocity.xy().magnitude() / 5.0).min(0.15));
74
75        next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
76
77        next.head.orientation = Quaternion::rotation_x(
78            (-0.5 + 0.2 * velocity.xy().magnitude() / 5.0).min(-0.3) + fast * 0.05,
79        );
80
81        next.beak.position = Vec3::new(0.0, s_a.beak.0, s_a.beak.1);
82
83        if velocity.z > 2.0 || velocity.xy().magnitude() < 12.0 {
84            next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1 - flap4 * 1.5);
85            next.chest.orientation = Quaternion::rotation_x(
86                (0.8 - 0.8 * velocity.xy().magnitude() / 5.0).max(-0.2) - flap1 * 0.2,
87            ) * Quaternion::rotation_y(tilt * 1.8 + fast * 0.01);
88            if s_a.wyvern {
89                next.wing_in_l.position =
90                    Vec3::new(-s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2 + 2.0);
91                next.wing_in_r.position =
92                    Vec3::new(s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2 + 2.0);
93            } else {
94                next.wing_in_l.position = Vec3::new(-s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2);
95                next.wing_in_r.position = Vec3::new(s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2);
96            }
97            next.wing_in_l.orientation =
98                Quaternion::rotation_y(-flap1 * 1.9 + 0.2) * Quaternion::rotation_x(0.4);
99            next.wing_in_r.orientation =
100                Quaternion::rotation_y(flap1 * 1.9 - 0.2) * Quaternion::rotation_x(0.4);
101
102            next.wing_mid_l.position = Vec3::new(-s_a.wing_mid.0, s_a.wing_mid.1, s_a.wing_mid.2);
103            next.wing_mid_r.position = Vec3::new(s_a.wing_mid.0, s_a.wing_mid.1, s_a.wing_mid.2);
104            next.wing_mid_l.orientation = Quaternion::rotation_y(-flap2 * 1.4 - 0.2);
105            next.wing_mid_r.orientation = Quaternion::rotation_y(flap2 * 1.4 + 0.2);
106
107            next.wing_out_l.position = Vec3::new(-s_a.wing_out.0, s_a.wing_out.1, s_a.wing_out.2);
108            next.wing_out_r.position = Vec3::new(s_a.wing_out.0, s_a.wing_out.1, s_a.wing_out.2);
109
110            if s_a.wyvern {
111                next.wing_out_l.orientation = Quaternion::rotation_y(-flap3 * 0.6 - 0.3);
112                next.wing_out_r.orientation = Quaternion::rotation_y(flap3 * 0.6 + 0.3);
113            } else {
114                next.wing_out_l.orientation = Quaternion::rotation_y(-flap3 * 1.2 - 0.3);
115                next.wing_out_r.orientation = Quaternion::rotation_y(flap3 * 1.2 + 0.3);
116            }
117
118            next.tail_front.position = Vec3::new(0.0, s_a.tail_front.0, s_a.tail_front.1);
119            next.tail_front.orientation =
120                Quaternion::rotation_x(-flap2 * 0.2 + 0.1) * Quaternion::rotation_z(tilt * 1.0);
121            next.tail_rear.position = Vec3::new(0.0, s_a.tail_rear.0, s_a.tail_rear.1);
122            next.tail_rear.orientation =
123                Quaternion::rotation_x(-flap3 * 0.3 + 0.15) * Quaternion::rotation_z(tilt * 0.8);
124
125            next.leg_l.position = Vec3::new(-s_a.leg.0, s_a.leg.1, s_a.leg.2 - flap4 * 1.5);
126            next.leg_l.orientation = Quaternion::rotation_x(
127                (-1.0 * velocity.xy().magnitude() / 5.0).max(-1.2) + flap1 * -0.1,
128            ) * Quaternion::rotation_y(tilt * 1.6 + fast * 0.01);
129            next.leg_r.position = Vec3::new(s_a.leg.0, s_a.leg.1, s_a.leg.2 - flap4 * 1.5);
130            next.leg_r.orientation = Quaternion::rotation_x(
131                (-1.0 * velocity.xy().magnitude() / 5.0).max(-1.2) + flap1 * -0.1,
132            ) * Quaternion::rotation_y(tilt * 1.6 + fast * 0.01);
133
134            next.foot_l.position = Vec3::new(-s_a.foot.0, s_a.foot.1, s_a.foot.2);
135            next.foot_l.orientation = Quaternion::rotation_x(flap1 * -0.1);
136            next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
137            next.foot_r.orientation = Quaternion::rotation_x(flap1 * -0.1);
138        } else {
139            next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1 + slow * 0.05);
140            next.chest.orientation =
141                Quaternion::rotation_x(-0.2 + slow * 0.05 + (0.8 * velocity.z / 80.0).min(0.8))
142                    * Quaternion::rotation_y(tilt * 1.8 + fast * 0.01);
143            if s_a.wyvern {
144                next.wing_in_l.position =
145                    Vec3::new(-s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2 + 2.0);
146                next.wing_in_r.position =
147                    Vec3::new(s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2 + 2.0);
148            } else {
149                next.wing_in_l.position = Vec3::new(-s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2);
150                next.wing_in_r.position = Vec3::new(s_a.wing_in.0, s_a.wing_in.1, s_a.wing_in.2);
151            }
152
153            next.wing_in_l.orientation =
154                Quaternion::rotation_y(0.1 + slow * 0.04 + (0.8 * velocity.z / 80.0).min(0.8))
155                    * Quaternion::rotation_x(0.4);
156            next.wing_in_r.orientation =
157                Quaternion::rotation_y(-0.1 + slow * -0.04 - (0.8 * velocity.z / 80.0).min(0.8))
158                    * Quaternion::rotation_x(0.4);
159
160            next.wing_mid_l.position = Vec3::new(-s_a.wing_mid.0, s_a.wing_mid.1, s_a.wing_mid.2);
161            next.wing_mid_r.position = Vec3::new(s_a.wing_mid.0, s_a.wing_mid.1, s_a.wing_mid.2);
162            next.wing_mid_l.orientation = Quaternion::rotation_y(0.1 + slow * 0.04);
163            next.wing_mid_r.orientation = Quaternion::rotation_y(-0.1 + slow * -0.04);
164
165            next.wing_out_l.position = Vec3::new(-s_a.wing_out.0, s_a.wing_out.1, s_a.wing_out.2);
166            next.wing_out_r.position = Vec3::new(s_a.wing_out.0, s_a.wing_out.1, s_a.wing_out.2);
167            next.wing_out_l.orientation =
168                Quaternion::rotation_y(0.1 + slow * 0.04 + (0.4 * velocity.z / 80.0).min(0.2));
169            next.wing_out_r.orientation =
170                Quaternion::rotation_y(-0.1 + slow * -0.04 - (0.4 * velocity.z / 80.0).min(0.2));
171
172            next.tail_front.position = Vec3::new(0.0, s_a.tail_front.0, s_a.tail_front.1);
173            next.tail_front.orientation =
174                Quaternion::rotation_x(0.04 - slow * 0.04) * Quaternion::rotation_z(tilt * 1.0);
175            next.tail_rear.position = Vec3::new(0.0, s_a.tail_rear.0, s_a.tail_rear.1);
176            next.tail_rear.orientation =
177                Quaternion::rotation_x(slow * 0.08) * Quaternion::rotation_z(tilt * 0.8);
178
179            next.leg_l.position = Vec3::new(-s_a.leg.0, s_a.leg.1, s_a.leg.2 + slow * 0.05);
180            next.leg_l.orientation = Quaternion::rotation_x(-1.2 + slow * -0.05)
181                * Quaternion::rotation_y(tilt * 1.6 + fast * 0.01);
182            next.leg_r.position = Vec3::new(s_a.leg.0, s_a.leg.1, s_a.leg.2 + slow * 0.05);
183            next.leg_r.orientation = Quaternion::rotation_x(-1.2 + slow * -0.05)
184                * Quaternion::rotation_y(tilt * 1.6 + fast * 0.01);
185
186            next.foot_l.position = Vec3::new(-s_a.foot.0, s_a.foot.1, s_a.foot.2);
187            next.foot_l.orientation = Quaternion::rotation_x(slow * -0.05);
188            next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
189            next.foot_r.orientation = Quaternion::rotation_x(slow * -0.05);
190        }
191
192        next
193    }
194}