veloren_voxygen_anim/golem/
mod.rs

1pub mod alpha;
2pub mod beam;
3pub mod combomelee;
4pub mod idle;
5pub mod run;
6pub mod shockwave;
7pub mod shoot;
8
9// Reexports
10pub use self::{
11    alpha::AlphaAnimation, beam::BeamAnimation, combomelee::ComboAnimation, idle::IdleAnimation,
12    run::RunAnimation, shockwave::ShockwaveAnimation, shoot::ShootAnimation,
13};
14
15use super::{FigureBoneData, Offsets, Skeleton, make_bone, vek::*};
16use common::comp::{self};
17use core::convert::TryFrom;
18
19pub type Body = comp::golem::Body;
20
21skeleton_impls!(struct GolemSkeleton {
22    + head,
23    + jaw,
24    + upper_torso,
25    + lower_torso,
26    + shoulder_l,
27    + shoulder_r,
28    + hand_l,
29    + hand_r,
30    + leg_l,
31    + leg_r,
32    + foot_l,
33    + foot_r,
34    torso,
35});
36
37impl Skeleton for GolemSkeleton {
38    type Attr = SkeletonAttr;
39    type Body = Body;
40
41    const BONE_COUNT: usize = 12;
42    #[cfg(feature = "use-dyn-lib")]
43    const COMPUTE_FN: &'static [u8] = b"golem_compute_mats\0";
44
45    #[cfg_attr(feature = "be-dyn-lib", export_name = "golem_compute_mats")]
46    fn compute_matrices_inner(
47        &self,
48        base_mat: Mat4<f32>,
49        buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
50        body: Self::Body,
51    ) -> Offsets {
52        let base_mat = base_mat * Mat4::scaling_3d(SkeletonAttr::from(&body).scaler / 8.0);
53
54        let torso_mat = base_mat * Mat4::<f32>::from(self.torso);
55        let upper_torso_mat = torso_mat * Mat4::<f32>::from(self.upper_torso);
56        let lower_torso_mat = upper_torso_mat * Mat4::<f32>::from(self.lower_torso);
57        let leg_l_mat = lower_torso_mat * Mat4::<f32>::from(self.leg_l);
58        let leg_r_mat = lower_torso_mat * Mat4::<f32>::from(self.leg_r);
59        let shoulder_l_mat = upper_torso_mat * Mat4::<f32>::from(self.shoulder_l);
60        let shoulder_r_mat = upper_torso_mat * Mat4::<f32>::from(self.shoulder_r);
61        let head_mat = upper_torso_mat * Mat4::<f32>::from(self.head);
62
63        *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
64            make_bone(head_mat),
65            make_bone(upper_torso_mat * Mat4::<f32>::from(self.head) * Mat4::<f32>::from(self.jaw)),
66            make_bone(upper_torso_mat),
67            make_bone(lower_torso_mat),
68            make_bone(upper_torso_mat * Mat4::<f32>::from(self.shoulder_l)),
69            make_bone(upper_torso_mat * Mat4::<f32>::from(self.shoulder_r)),
70            make_bone(shoulder_l_mat * Mat4::<f32>::from(self.hand_l)),
71            make_bone(shoulder_r_mat * Mat4::<f32>::from(self.hand_r)),
72            make_bone(leg_l_mat),
73            make_bone(leg_r_mat),
74            make_bone(leg_l_mat * Mat4::<f32>::from(self.foot_l)),
75            make_bone(leg_r_mat * Mat4::<f32>::from(self.foot_r)),
76        ];
77
78        let (mount_mat, mount_orientation) = (
79            head_mat,
80            self.torso.orientation * self.upper_torso.orientation * self.head.orientation,
81        );
82        let mount_position = mount_mat.mul_point(mount_point(&body));
83
84        Offsets {
85            viewpoint: Some((head_mat * Vec4::new(0.0, 0.0, 5.0, 1.0)).xyz()),
86            // TODO: see quadruped_medium for how to animate this
87            mount_bone: Transform {
88                position: mount_position,
89                orientation: mount_orientation,
90                scale: Vec3::one(),
91            },
92            ..Default::default()
93        }
94    }
95}
96
97pub struct SkeletonAttr {
98    head: (f32, f32),
99    jaw: (f32, f32),
100    upper_torso: (f32, f32),
101    lower_torso: (f32, f32),
102    shoulder: (f32, f32, f32),
103    hand: (f32, f32, f32),
104    leg: (f32, f32, f32),
105    foot: (f32, f32, f32),
106    scaler: f32,
107    tempo: f32,
108}
109
110impl<'a> TryFrom<&'a comp::Body> for SkeletonAttr {
111    type Error = ();
112
113    fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
114        match body {
115            comp::Body::Golem(body) => Ok(SkeletonAttr::from(body)),
116            _ => Err(()),
117        }
118    }
119}
120
121impl Default for SkeletonAttr {
122    fn default() -> Self {
123        Self {
124            head: (0.0, 0.0),
125            jaw: (0.0, 0.0),
126            upper_torso: (0.0, 0.0),
127            lower_torso: (0.0, 0.0),
128            shoulder: (0.0, 0.0, 0.0),
129            hand: (0.0, 0.0, 0.0),
130            leg: (0.0, 0.0, 0.0),
131            foot: (0.0, 0.0, 0.0),
132            scaler: 0.0,
133            tempo: 0.0,
134        }
135    }
136}
137
138impl<'a> From<&'a Body> for SkeletonAttr {
139    fn from(body: &'a Body) -> Self {
140        use comp::golem::Species::*;
141        Self {
142            head: match (body.species, body.body_type) {
143                (StoneGolem, _) => (0.0, 2.0),
144                (Treant, _) => (18.0, -8.0),
145                (ClayGolem, _) => (0.0, 7.0),
146                (WoodGolem, _) => (3.0, 6.0),
147                (CoralGolem, _) => (-1.0, 3.0),
148                (Gravewarden, _) => (-2.0, 7.0),
149                (AncientEffigy, _) => (-2.0, 8.0),
150                (Mogwai, _) => (-8.0, 2.0),
151                (IronGolem, _) => (0.0, 3.0),
152            },
153            jaw: match (body.species, body.body_type) {
154                (StoneGolem, _) => (0.0, 0.0),
155                (Treant, _) => (-6.5, -1.0),
156                (ClayGolem, _) => (0.0, 0.0),
157                (WoodGolem, _) => (0.0, 0.0),
158                (CoralGolem, _) => (0.0, 0.0),
159                (Gravewarden, _) => (0.0, 0.0),
160                (AncientEffigy, _) => (0.0, 0.0),
161                (Mogwai, _) => (-6.0, -5.0),
162                (IronGolem, _) => (0.0, 0.0),
163            },
164            upper_torso: match (body.species, body.body_type) {
165                (StoneGolem, _) => (0.0, 34.5),
166                (Treant, _) => (0.0, 28.5),
167                (ClayGolem, _) => (0.0, 23.0),
168                (WoodGolem, _) => (0.0, 24.5),
169                (CoralGolem, _) => (0.0, 25.0),
170                (Gravewarden, _) => (0.0, 26.5),
171                (AncientEffigy, _) => (0.0, 18.0),
172                (Mogwai, _) => (0.0, 18.0),
173                (IronGolem, _) => (0.0, 34.5),
174            },
175            lower_torso: match (body.species, body.body_type) {
176                (StoneGolem, _) => (0.0, -10.5),
177                (Treant, _) => (0.0, -10.5),
178                (ClayGolem, _) => (0.0, -7.5),
179                (WoodGolem, _) => (0.0, -4.5),
180                (CoralGolem, _) => (0.0, -11.5),
181                (Gravewarden, _) => (0.0, -4.5),
182                (AncientEffigy, _) => (0.0, -4.5),
183                (Mogwai, _) => (0.0, -4.5),
184                (IronGolem, _) => (0.0, -10.5),
185            },
186            shoulder: match (body.species, body.body_type) {
187                (StoneGolem, _) => (8.0, -1.5, 4.0),
188                (Treant, _) => (8.0, 4.5, -3.0),
189                (ClayGolem, _) => (8.0, -1.0, -1.0),
190                (WoodGolem, _) => (6.0, 2.0, 1.0),
191                (CoralGolem, _) => (11.0, 1.0, 0.0),
192                (Gravewarden, _) => (8.0, 2.0, 3.0),
193                (AncientEffigy, _) => (8.0, 2.0, 3.0),
194                (Mogwai, _) => (8.0, 2.0, 3.0),
195                (IronGolem, _) => (8.0, -1.5, 0.0),
196            },
197            hand: match (body.species, body.body_type) {
198                (StoneGolem, _) => (12.5, -1.0, -7.0),
199                (Treant, _) => (8.5, -1.0, -7.0),
200                (ClayGolem, _) => (6.5, 0.0, -2.0),
201                (WoodGolem, _) => (5.5, -1.0, -6.0),
202                (CoralGolem, _) => (2.5, -1.5, -5.0),
203                (Gravewarden, _) => (8.5, -1.0, -7.0),
204                (AncientEffigy, _) => (8.5, -1.0, -7.0),
205                (Mogwai, _) => (8.5, -1.0, -7.0),
206                (IronGolem, _) => (12.5, -1.0, -7.0),
207            },
208            leg: match (body.species, body.body_type) {
209                (StoneGolem, _) => (4.0, 0.0, -3.5),
210                (Treant, _) => (2.0, 9.5, -1.0),
211                (ClayGolem, _) => (1.0, 0.0, -3.0),
212                (WoodGolem, _) => (2.0, 0.5, -6.0),
213                (CoralGolem, _) => (2.5, 0.5, -3.0),
214                (Gravewarden, _) => (1.0, 0.5, -6.0),
215                (AncientEffigy, _) => (1.0, 0.5, -6.0),
216                (Mogwai, _) => (1.0, 0.5, -6.0),
217                (IronGolem, _) => (1.5, 1.5, -3.5),
218            },
219            foot: match (body.species, body.body_type) {
220                (StoneGolem, _) => (3.5, 0.5, -9.5),
221                (Treant, _) => (3.5, -5.0, -8.5),
222                (ClayGolem, _) => (3.5, 0.0, -5.5),
223                (WoodGolem, _) => (2.5, 1.0, -5.5),
224                (CoralGolem, _) => (2.5, 1.0, -1.5),
225                (Gravewarden, _) => (3.5, -1.0, -8.5),
226                (AncientEffigy, _) => (3.5, -1.0, -8.5),
227                (Mogwai, _) => (3.5, -1.0, -8.5),
228                (IronGolem, _) => (3.5, 0.5, -9.5),
229            },
230            scaler: match (body.species, body.body_type) {
231                (StoneGolem, _) => 1.5,
232                (Treant, _) => 1.5,
233                (ClayGolem, _) => 1.5,
234                (WoodGolem, _) => 1.5,
235                (CoralGolem, _) => 1.0,
236                (Gravewarden, _) => 1.5,
237                (AncientEffigy, _) => 1.0,
238                (Mogwai, _) => 1.0,
239                (IronGolem, _) => 1.5,
240            },
241            tempo: match (body.species, body.body_type) {
242                (StoneGolem, _) => 1.0,
243                (Treant, _) => 1.0,
244                (ClayGolem, _) => 1.0,
245                (WoodGolem, _) => 1.0,
246                (CoralGolem, _) => 1.0,
247                (Gravewarden, _) => 1.0,
248                (AncientEffigy, _) => 1.0,
249                (Mogwai, _) => 1.0,
250                (IronGolem, _) => 1.0,
251            },
252        }
253    }
254}
255
256fn mount_point(body: &Body) -> Vec3<f32> {
257    use comp::golem::Species::*;
258    match (body.species, body.body_type) {
259        (StoneGolem, _) => (0.0, 0.5, 10.0),
260        (Treant, _) => (0.0, 0.0, 14.0),
261        (ClayGolem, _) => (0.0, 0.0, 12.0),
262        (WoodGolem, _) => (0.0, 0.0, 8.0),
263        (CoralGolem, _) => (0.0, 0.0, 5.0),
264        (Gravewarden, _) => (0.0, -0.5, 7.0),
265        (AncientEffigy, _) => (0.0, -0.5, 4.0),
266        (Mogwai, _) => (0.0, 11.0, 10.5),
267        (IronGolem, _) => (0.0, 0.0, 17.0),
268    }
269    .into()
270}