veloren_voxygen_anim/fish_medium/
mod.rs

1pub mod idle;
2pub mod swim;
3
4// Reexports
5pub use self::{idle::IdleAnimation, swim::SwimAnimation};
6
7use super::{FigureBoneData, Offsets, Skeleton, make_bone, vek::*};
8use common::comp::{self};
9use core::convert::TryFrom;
10
11pub type Body = comp::fish_medium::Body;
12
13skeleton_impls!(struct FishMediumSkeleton {
14    + head,
15    + jaw,
16    + chest_front,
17    + chest_back,
18    + tail,
19    + fin_l,
20    + fin_r,
21});
22
23impl Skeleton for FishMediumSkeleton {
24    type Attr = SkeletonAttr;
25    type Body = Body;
26
27    const BONE_COUNT: usize = 7;
28    #[cfg(feature = "use-dyn-lib")]
29    const COMPUTE_FN: &'static [u8] = b"fish_medium_compute_mats\0";
30
31    #[cfg_attr(
32        feature = "be-dyn-lib",
33        unsafe(export_name = "fish_medium_compute_mats")
34    )]
35    fn compute_matrices_inner(
36        &self,
37        base_mat: Mat4<f32>,
38        buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
39        body: Self::Body,
40    ) -> Offsets {
41        let base_mat = base_mat * Mat4::scaling_3d(1.0 / 11.0);
42
43        let chest_front_mat = base_mat * Mat4::<f32>::from(self.chest_front);
44        let chest_back_mat = Mat4::<f32>::from(self.chest_back);
45        let head_mat = chest_front_mat * Mat4::<f32>::from(self.head);
46
47        *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
48            make_bone(head_mat),
49            make_bone(head_mat * Mat4::<f32>::from(self.jaw)),
50            make_bone(chest_front_mat),
51            make_bone(chest_front_mat * chest_back_mat),
52            make_bone(chest_front_mat * chest_back_mat * Mat4::<f32>::from(self.tail)),
53            make_bone(chest_front_mat * Mat4::<f32>::from(self.fin_l)),
54            make_bone(chest_front_mat * Mat4::<f32>::from(self.fin_r)),
55        ];
56
57        let (mount_bone_mat, mount_bone_ori) = (head_mat, self.head.orientation);
58        let mount_position = mount_bone_mat.mul_point(mount_point(&body));
59        let mount_orientation = mount_bone_ori;
60
61        Offsets {
62            viewpoint: Some((head_mat * Vec4::new(0.0, 5.0, 0.0, 1.0)).xyz()),
63            // TODO: see quadruped_medium for how to animate this
64            mount_bone: Transform {
65                position: mount_position,
66                orientation: mount_orientation,
67                scale: Vec3::one(),
68            },
69            ..Default::default()
70        }
71    }
72}
73
74pub struct SkeletonAttr {
75    head: (f32, f32),
76    jaw: (f32, f32),
77    chest_front: (f32, f32),
78    chest_back: (f32, f32),
79    tail: (f32, f32),
80    fin: (f32, f32, f32),
81    tempo: f32,
82    amplitude: f32,
83}
84
85impl<'a> TryFrom<&'a comp::Body> for SkeletonAttr {
86    type Error = ();
87
88    fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
89        match body {
90            comp::Body::FishMedium(body) => Ok(SkeletonAttr::from(body)),
91            _ => Err(()),
92        }
93    }
94}
95
96impl Default for SkeletonAttr {
97    fn default() -> Self {
98        Self {
99            head: (0.0, 0.0),
100            jaw: (0.0, 0.0),
101            chest_front: (0.0, 0.0),
102            chest_back: (0.0, 0.0),
103            tail: (0.0, 0.0),
104            fin: (0.0, 0.0, 0.0),
105            tempo: 0.0,
106            amplitude: 0.0,
107        }
108    }
109}
110
111impl<'a> From<&'a Body> for SkeletonAttr {
112    fn from(body: &'a Body) -> Self {
113        use comp::fish_medium::Species::*;
114        Self {
115            head: match (body.species, body.body_type) {
116                (Marlin, _) => (2.0, 1.5),
117                (Icepike, _) => (3.0, 1.0),
118            },
119            jaw: match (body.species, body.body_type) {
120                (Marlin, _) => (2.5, -3.0),
121                (Icepike, _) => (0.0, 0.0),
122            },
123            chest_front: match (body.species, body.body_type) {
124                (Marlin, _) => (0.0, 2.5),
125                (Icepike, _) => (0.0, 2.5),
126            },
127            chest_back: match (body.species, body.body_type) {
128                (Marlin, _) => (-1.0, 1.0),
129                (Icepike, _) => (-4.5, 0.0),
130            },
131            tail: match (body.species, body.body_type) {
132                (Marlin, _) => (-7.0, 0.0),
133                (Icepike, _) => (-0.5, 1.5),
134            },
135            fin: match (body.species, body.body_type) {
136                (Marlin, _) => (2.5, 1.0, 3.5),
137                (Icepike, _) => (3.5, 3.0, 0.0),
138            },
139            tempo: match (body.species, body.body_type) {
140                (Marlin, _) => 4.0,
141                (Icepike, _) => 4.0,
142            },
143            amplitude: match (body.species, body.body_type) {
144                (Marlin, _) => 4.0,
145                (Icepike, _) => 4.0,
146            },
147        }
148    }
149}
150
151fn mount_point(body: &Body) -> Vec3<f32> {
152    use comp::fish_medium::Species::*;
153    match (body.species, body.body_type) {
154        (Marlin, _) => (0.0, 0.5, 3.0),
155        (Icepike, _) => (0.0, 0.5, 4.0),
156    }
157    .into()
158}