diff --git a/assets/voxygen/voxel/npc/duck_m/duck_m_body.vox b/assets/voxygen/voxel/npc/duck_m/duck_m_body.vox new file mode 100644 index 0000000000..19a3ba1a3b --- /dev/null +++ b/assets/voxygen/voxel/npc/duck_m/duck_m_body.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:695d8f719c5bb550643cf3e276cc984ee0953e35cba3da7a0d17bce9b3b8f2dd +size 56063 diff --git a/assets/voxygen/voxel/npc/duck_m/duck_m_head.vox b/assets/voxygen/voxel/npc/duck_m/duck_m_head.vox new file mode 100644 index 0000000000..466c83223b --- /dev/null +++ b/assets/voxygen/voxel/npc/duck_m/duck_m_head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b8c1abcecd2c0cc979d2babe83d3797949a986dab1580f50097b08ebe919a190 +size 55703 diff --git a/assets/voxygen/voxel/npc/duck_m/duck_m_leg_l.vox b/assets/voxygen/voxel/npc/duck_m/duck_m_leg_l.vox new file mode 100644 index 0000000000..515df8f571 --- /dev/null +++ b/assets/voxygen/voxel/npc/duck_m/duck_m_leg_l.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:804f7a03dae44eaf54e36c424b7ec00b2c345f8d9f5326f7769ee01aca65a6cb +size 55615 diff --git a/assets/voxygen/voxel/npc/duck_m/duck_m_leg_r.vox b/assets/voxygen/voxel/npc/duck_m/duck_m_leg_r.vox new file mode 100644 index 0000000000..0257a695e9 --- /dev/null +++ b/assets/voxygen/voxel/npc/duck_m/duck_m_leg_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60ff0228f74dae0a6c0b7624b031e38032f473fe40c8bf28a3e71144e64ae4cf +size 55615 diff --git a/assets/voxygen/voxel/npc/duck_m/duck_m_tail.vox b/assets/voxygen/voxel/npc/duck_m/duck_m_tail.vox new file mode 100644 index 0000000000..62d1a47a18 --- /dev/null +++ b/assets/voxygen/voxel/npc/duck_m/duck_m_tail.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:29b27c5210140ece6e914c356b7c92e2cdf118c46a520ee06ec21be6490c988e +size 55643 diff --git a/assets/voxygen/voxel/npc/duck_m/duck_m_wing.vox b/assets/voxygen/voxel/npc/duck_m/duck_m_wing.vox new file mode 100644 index 0000000000..afea120592 --- /dev/null +++ b/assets/voxygen/voxel/npc/duck_m/duck_m_wing.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ed2820afb08af1175ddad78a2a429d57cb9c951abdc0f1215498fd89ba59784 +size 55631 diff --git a/assets/voxygen/voxel/npc/marlin/marlin_fin_l.vox b/assets/voxygen/voxel/npc/marlin/marlin_fin_l.vox new file mode 100644 index 0000000000..4b6f517af8 --- /dev/null +++ b/assets/voxygen/voxel/npc/marlin/marlin_fin_l.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:80b0d57ec40c04bad6207cbd2443126cf731898df1f2586b26806c426c46ff5e +size 1152 diff --git a/assets/voxygen/voxel/npc/marlin/marlin_fin_r.vox b/assets/voxygen/voxel/npc/marlin/marlin_fin_r.vox new file mode 100644 index 0000000000..d208e485aa --- /dev/null +++ b/assets/voxygen/voxel/npc/marlin/marlin_fin_r.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aef2d194365db70e6a30551071f361863fad2f6c6a768f8c3368982363cdcdd6 +size 1152 diff --git a/assets/voxygen/voxel/npc/marlin/marlin_head.vox b/assets/voxygen/voxel/npc/marlin/marlin_head.vox new file mode 100644 index 0000000000..45a31f5b69 --- /dev/null +++ b/assets/voxygen/voxel/npc/marlin/marlin_head.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dcbe6707a2278ebd4828998b58d9fa69c2eba15b3b31f11de2e9104a9b59c1eb +size 1352 diff --git a/assets/voxygen/voxel/npc/marlin/marlin_rear.vox b/assets/voxygen/voxel/npc/marlin/marlin_rear.vox new file mode 100644 index 0000000000..ab15e4fc13 --- /dev/null +++ b/assets/voxygen/voxel/npc/marlin/marlin_rear.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dea03905c68b83f25f5196393ca8d06196b5a35eed0b12be61aa6bcfc8d5e081 +size 1360 diff --git a/assets/voxygen/voxel/npc/marlin/marlin_tail.vox b/assets/voxygen/voxel/npc/marlin/marlin_tail.vox new file mode 100644 index 0000000000..30a1696564 --- /dev/null +++ b/assets/voxygen/voxel/npc/marlin/marlin_tail.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1e55b9da2a45123b3109b763d741b550a11f274fc2563c4e54df17da389426c8 +size 1308 diff --git a/assets/voxygen/voxel/npc/marlin/marlin_torso.vox b/assets/voxygen/voxel/npc/marlin/marlin_torso.vox new file mode 100644 index 0000000000..1c0219ac08 --- /dev/null +++ b/assets/voxygen/voxel/npc/marlin/marlin_torso.vox @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e0398753b0ff2719940aa1e2f20430892ebee6b7da26b61d8b16dad5d826655a +size 1476 diff --git a/common/src/comp/body.rs b/common/src/comp/body.rs index 2ac56c58b1..a7ca75bba1 100644 --- a/common/src/comp/body.rs +++ b/common/src/comp/body.rs @@ -2,6 +2,8 @@ pub mod humanoid; pub mod object; pub mod quadruped; pub mod quadruped_medium; +pub mod bird_medium; +pub mod fish_medium; use specs::{Component, FlaggedStorage}; use specs_idvs::IDVStorage; @@ -11,6 +13,8 @@ pub enum Body { Humanoid(humanoid::Body), Quadruped(quadruped::Body), QuadrupedMedium(quadruped_medium::Body), + BirdMedium(bird_medium::Body), + FishMedium(fish_medium::Body), Object(object::Body), } diff --git a/common/src/comp/body/bird_medium.rs b/common/src/comp/body/bird_medium.rs new file mode 100644 index 0000000000..38a0cc438f --- /dev/null +++ b/common/src/comp/body/bird_medium.rs @@ -0,0 +1,68 @@ +use rand::{seq::SliceRandom, thread_rng}; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Body { + pub head: Head, + pub torso: Torso, + pub tail: Tail, + pub wing_l: WingL, + pub wing_r: WingR, + pub leg_l: LegL, + pub leg_r: LegR, +} +impl Body { + pub fn random() -> Self { + let mut rng = thread_rng(); + Self { + head: *(&ALL_HEADS).choose(&mut rng).unwrap(), + torso: *(&ALL_TORSOS).choose(&mut rng).unwrap(), + tail: *(&ALL_TAILS).choose(&mut rng).unwrap(), + wing_l: *(&ALL_WING_LS).choose(&mut rng).unwrap(), + wing_r: *(&ALL_WING_RS).choose(&mut rng).unwrap(), + leg_l: *(&ALL_LEG_LS).choose(&mut rng).unwrap(), + leg_r: *(&ALL_LEG_RS).choose(&mut rng).unwrap(), + } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Head { + Default, +} +const ALL_HEADS: [Head; 1] = [Head::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Torso { + Default, +} +const ALL_TORSOS: [Torso; 1] = [Torso::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Tail { + Default, +} +const ALL_TAILS: [Tail; 1] = [Tail::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum WingL { + Default, +} +const ALL_WING_LS: [WingL; 1] = [WingL::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum WingR { + Default, +} +const ALL_WING_RS: [WingR; 1] = [WingR::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum LegL { + Default, +} +const ALL_LEG_LS: [LegL; 1] = [LegL::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum LegR { + Default, +} +const ALL_LEG_RS: [LegR; 1] = [LegR::Default]; \ No newline at end of file diff --git a/common/src/comp/body/fish_medium.rs b/common/src/comp/body/fish_medium.rs new file mode 100644 index 0000000000..7da9bce91f --- /dev/null +++ b/common/src/comp/body/fish_medium.rs @@ -0,0 +1,61 @@ +use rand::{seq::SliceRandom, thread_rng}; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Body { + pub head: Head, + pub torso: Torso, + pub rear: Rear, + pub tail: Tail, + pub fin_l: FinL, + pub fin_r: FinR, +} +impl Body { + pub fn random() -> Self { + let mut rng = thread_rng(); + Self { + head: *(&ALL_HEADS).choose(&mut rng).unwrap(), + torso: *(&ALL_TORSOS).choose(&mut rng).unwrap(), + rear: *(&ALL_REARS).choose(&mut rng).unwrap(), + tail: *(&ALL_TAILS).choose(&mut rng).unwrap(), + fin_l: *(&ALL_FIN_LS).choose(&mut rng).unwrap(), + fin_r: *(&ALL_FIN_RS).choose(&mut rng).unwrap(), + + } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Head { + Default, +} +const ALL_HEADS: [Head; 1] = [Head::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Torso { + Default, +} +const ALL_TORSOS: [Torso; 1] = [Torso::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Rear { + Default, +} +const ALL_REARS: [Rear; 1] = [Rear::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum Tail { + Default, +} +const ALL_TAILS: [Tail; 1] = [Tail::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum FinL { + Default, +} +const ALL_FIN_LS: [FinL; 1] = [FinL::Default]; + +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum FinR { + Default, +} +const ALL_FIN_RS: [FinR; 1] = [FinR::Default]; diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index d79fb41ae7..2a0c67e3cd 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -16,7 +16,7 @@ mod visual; // Reexports pub use admin::Admin; pub use agent::Agent; -pub use body::{humanoid, object, quadruped, quadruped_medium, Body}; +pub use body::{humanoid, object, quadruped, quadruped_medium, bird_medium, fish_medium, Body}; pub use character_state::{ActionState, CharacterState, MovementState}; pub use controller::{ ControlEvent, Controller, ControllerInputs, InventoryManip, MountState, Mounting, diff --git a/common/src/npc.rs b/common/src/npc.rs index 3f95c17cca..0c0ebe25d5 100644 --- a/common/src/npc.rs +++ b/common/src/npc.rs @@ -30,6 +30,7 @@ impl FromStr for NpcKind { "humanoid" => Ok(NpcKind::Humanoid), "wolf" => Ok(NpcKind::Wolf), "pig" => Ok(NpcKind::Pig), + _ => Err(()), } } diff --git a/voxygen/src/anim/birdmedium/idle.rs b/voxygen/src/anim/birdmedium/idle.rs new file mode 100644 index 0000000000..b3770c6142 --- /dev/null +++ b/voxygen/src/anim/birdmedium/idle.rs @@ -0,0 +1,74 @@ +use super::{ + super::{Animation, SkeletonAttr}, + BirdMediumSkeleton, +}; +use std::{f32::consts::PI, ops::Mul}; +use vek::*; + +pub struct IdleAnimation; + +impl Animation for IdleAnimation { + type Skeleton = BirdMediumSkeleton; + type Dependency = (f64); + + fn update_skeleton( + skeleton: &Self::Skeleton, + global_time: Self::Dependency, + anim_time: f64, + _rate: &mut f32, + _skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin(); + let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos(); + let wave_slow = (anim_time as f32 * 3.5 + PI).sin(); + let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos(); + + let duck_m_look = Vec2::new( + ((global_time + anim_time) as f32 / 8.0) + .floor() + .mul(7331.0) + .sin() + * 0.5, + ((global_time + anim_time) as f32 / 8.0) + .floor() + .mul(1337.0) + .sin() + * 0.25, + ); + + + next.duck_m_head.offset = Vec3::new(0.0, 7.5, 15.0) / 11.0; + next.duck_m_head.ori = + Quaternion::rotation_z(duck_m_look.x) * Quaternion::rotation_x(duck_m_look.y); + next.duck_m_head.scale = Vec3::one() / 10.88; + + next.duck_m_torso.offset = + Vec3::new(0.0, 4.5 - wave_ultra_slow_cos * 0.12, 2.0); + next.duck_m_torso.ori = Quaternion::rotation_x(0.0); + next.duck_m_torso.scale = Vec3::one() * 1.01; + + next.duck_m_tail.offset = Vec3::new(0.0, 3.1, -4.5); + next.duck_m_tail.ori = Quaternion::rotation_z(0.0); + next.duck_m_tail.scale = Vec3::one() * 0.98; + + next.duck_m_wing_l.offset = Vec3::new(0.0, -13.0, 8.0) / 11.0; + next.duck_m_wing_l.ori = Quaternion::rotation_z(0.0) + * Quaternion::rotation_x(0.0); + next.duck_m_wing_l.scale = Vec3::one() / 11.0; + + next.duck_m_wing_r.offset = Vec3::new(0.0, -11.7, 11.0) / 11.0; + next.duck_m_wing_r.ori = Quaternion::rotation_y(0.0); + next.duck_m_wing_r.scale = Vec3::one() / 11.0; + + next.duck_m_leg_l.offset = Vec3::new(0.0, 0.0, 12.0) / 11.0; + next.duck_m_leg_l.ori = Quaternion::rotation_y(0.0); + next.duck_m_leg_l.scale = Vec3::one() / 10.5; + + next.duck_m_leg_r.offset = Vec3::new(0.0, 0.75, 5.25); + next.duck_m_leg_r.ori = Quaternion::rotation_x(0.0); + next.duck_m_leg_r.scale = Vec3::one() * 1.00; + next + } +} diff --git a/voxygen/src/anim/birdmedium/jump.rs b/voxygen/src/anim/birdmedium/jump.rs new file mode 100644 index 0000000000..191412c2d5 --- /dev/null +++ b/voxygen/src/anim/birdmedium/jump.rs @@ -0,0 +1,62 @@ +use super::{ + super::{Animation, SkeletonAttr}, + BirdMediumSkeleton, +}; +use std::f32::consts::PI; +use vek::*; + +pub struct JumpAnimation; + +impl Animation for JumpAnimation { + type Skeleton = BirdMediumSkeleton; + type Dependency = (f32, f64); + + fn update_skeleton( + skeleton: &Self::Skeleton, + _global_time: Self::Dependency, + anim_time: f64, + _rate: &mut f32, + _skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin(); + let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos(); + let wave_slow = (anim_time as f32 * 3.5 + PI).sin(); + let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos(); + + + + next.duck_m_head.offset = Vec3::new(0.0, 7.5, 15.0) / 11.0; + next.duck_m_head.ori = + Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0); + next.duck_m_head.scale = Vec3::one() / 10.88; + + next.duck_m_torso.offset = + Vec3::new(0.0, 4.5 - wave_ultra_slow_cos * 0.12, 2.0); + next.duck_m_torso.ori = Quaternion::rotation_x(0.0); + next.duck_m_torso.scale = Vec3::one() * 1.01; + + next.duck_m_tail.offset = Vec3::new(0.0, 3.1, -4.5); + next.duck_m_tail.ori = Quaternion::rotation_z(0.0); + next.duck_m_tail.scale = Vec3::one() * 0.98; + + next.duck_m_wing_l.offset = Vec3::new(0.0, -13.0, 8.0) / 11.0; + next.duck_m_wing_l.ori = Quaternion::rotation_z(0.0) + * Quaternion::rotation_x(0.0); + next.duck_m_wing_l.scale = Vec3::one() / 11.0; + + next.duck_m_wing_r.offset = Vec3::new(0.0, -11.7, 11.0) / 11.0; + next.duck_m_wing_r.ori = Quaternion::rotation_y(0.0); + next.duck_m_wing_r.scale = Vec3::one() / 11.0; + + next.duck_m_leg_l.offset = Vec3::new(0.0, 0.0, 12.0) / 11.0; + next.duck_m_leg_l.ori = Quaternion::rotation_y(0.0); + next.duck_m_leg_l.scale = Vec3::one() / 10.5; + + next.duck_m_leg_r.offset = Vec3::new(0.0, 0.75, 5.25); + next.duck_m_leg_r.ori = Quaternion::rotation_x(0.0); + next.duck_m_leg_r.scale = Vec3::one() * 1.00; + next + } +} \ No newline at end of file diff --git a/voxygen/src/anim/birdmedium/mod.rs b/voxygen/src/anim/birdmedium/mod.rs new file mode 100644 index 0000000000..53292603ba --- /dev/null +++ b/voxygen/src/anim/birdmedium/mod.rs @@ -0,0 +1,80 @@ +pub mod idle; +pub mod jump; +pub mod run; + +// Reexports +pub use self::idle::IdleAnimation; +pub use self::jump::JumpAnimation; +pub use self::run::RunAnimation; + +use super::{Bone, Skeleton}; +use crate::render::FigureBoneData; + +#[derive(Clone)] +pub struct BirdMediumSkeleton { + duck_m_head: Bone, + duck_m_torso: Bone, + duck_m_tail: Bone, + duck_m_wing_l: Bone, + duck_m_wing_r: Bone, + duck_m_leg_l: Bone, + duck_m_leg_r: Bone, + +} + +impl BirdMediumSkeleton { + pub fn new() -> Self { + Self { + duck_m_head: Bone::default(), + duck_m_torso: Bone::default(), + duck_m_tail: Bone::default(), + duck_m_wing_l: Bone::default(), + duck_m_wing_r: Bone::default(), + duck_m_leg_l: Bone::default(), + duck_m_leg_r: Bone::default(), + + + } + } +} + +impl Skeleton for BirdMediumSkeleton { + fn compute_matrices(&self) -> [FigureBoneData; 16] { + let torso_mat = self.duck_m_torso.compute_base_matrix(); + + + [ + FigureBoneData::new(self.duck_m_head.compute_base_matrix() * torso_mat), + FigureBoneData::new( + torso_mat, + ), + FigureBoneData::new(self.duck_m_tail.compute_base_matrix() * torso_mat), + FigureBoneData::new(self.duck_m_wing_l.compute_base_matrix() * torso_mat), + FigureBoneData::new(self.duck_m_wing_r.compute_base_matrix() * torso_mat), + FigureBoneData::new(self.duck_m_leg_l.compute_base_matrix()), + FigureBoneData::new(self.duck_m_leg_r.compute_base_matrix()), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + ] + } + + fn interpolate(&mut self, target: &Self, dt: f32) { + self.duck_m_head + .interpolate(&target.duck_m_head, dt); + self.duck_m_torso.interpolate(&target.duck_m_torso, dt); + self.duck_m_tail + .interpolate(&target.duck_m_tail, dt); + self.duck_m_wing_l.interpolate(&target.duck_m_wing_l, dt); + self.duck_m_wing_r + .interpolate(&target.duck_m_wing_r, dt); + self.duck_m_leg_l.interpolate(&target.duck_m_leg_l, dt); + self.duck_m_leg_r.interpolate(&target.duck_m_leg_r, dt); + } +} diff --git a/voxygen/src/anim/birdmedium/run.rs b/voxygen/src/anim/birdmedium/run.rs new file mode 100644 index 0000000000..ac940f6ae7 --- /dev/null +++ b/voxygen/src/anim/birdmedium/run.rs @@ -0,0 +1,74 @@ +use super::{ + super::{Animation, SkeletonAttr}, + BirdMediumSkeleton, +}; +use std::{f32::consts::PI, ops::Mul}; +use vek::*; + +pub struct RunAnimation; + +impl Animation for RunAnimation { + type Skeleton = BirdMediumSkeleton; + type Dependency = (f32, f64); + + fn update_skeleton( + skeleton: &Self::Skeleton, + (_velocity, global_time): Self::Dependency, + anim_time: f64, + _rate: &mut f32, + _skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin(); + let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos(); + let wave_slow = (anim_time as f32 * 3.5 + PI).sin(); + let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos(); + + let duck_look = Vec2::new( + ((global_time + anim_time) as f32 / 8.0) + .floor() + .mul(7331.0) + .sin() + * 0.5, + ((global_time + anim_time) as f32 / 8.0) + .floor() + .mul(1337.0) + .sin() + * 0.25, + ); + + + next.duck_m_head.offset = Vec3::new(0.0, 7.5, 15.0) / 11.0; + next.duck_m_head.ori = + Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0); + next.duck_m_head.scale = Vec3::one() / 10.88; + + next.duck_m_torso.offset = + Vec3::new(0.0, 4.5 - wave_ultra_slow_cos * 0.12, 2.0); + next.duck_m_torso.ori = Quaternion::rotation_x(0.0); + next.duck_m_torso.scale = Vec3::one() * 1.01; + + next.duck_m_tail.offset = Vec3::new(0.0, 3.1, -4.5); + next.duck_m_tail.ori = Quaternion::rotation_z(0.0); + next.duck_m_tail.scale = Vec3::one() * 0.98; + + next.duck_m_wing_l.offset = Vec3::new(0.0, -13.0, 8.0) / 11.0; + next.duck_m_wing_l.ori = Quaternion::rotation_z(0.0) + * Quaternion::rotation_x(0.0); + next.duck_m_wing_l.scale = Vec3::one() / 11.0; + + next.duck_m_wing_r.offset = Vec3::new(0.0, -11.7, 11.0) / 11.0; + next.duck_m_wing_r.ori = Quaternion::rotation_y(0.0); + next.duck_m_wing_r.scale = Vec3::one() / 11.0; + + next.duck_m_leg_l.offset = Vec3::new(0.0, 0.0, 12.0) / 11.0; + next.duck_m_leg_l.ori = Quaternion::rotation_y(0.0); + next.duck_m_leg_l.scale = Vec3::one() / 10.5; + + next.duck_m_leg_r.offset = Vec3::new(0.0, 0.75, 5.25); + next.duck_m_leg_r.ori = Quaternion::rotation_x(0.0); + next.duck_m_leg_r.scale = Vec3::one() * 1.00; + next + } +} \ No newline at end of file diff --git a/voxygen/src/anim/character/run - Copy.rs b/voxygen/src/anim/character/run - Copy.rs new file mode 100644 index 0000000000..6e0a6aff0b --- /dev/null +++ b/voxygen/src/anim/character/run - Copy.rs @@ -0,0 +1,147 @@ +use super::{ + super::{Animation, SkeletonAttr}, + CharacterSkeleton, +}; +use std::f32::consts::PI; +use std::ops::Mul; +use vek::*; + +pub struct SneakAnimation; + +impl Animation for SneakAnimation { + type Skeleton = CharacterSkeleton; + type Dependency = (Vec3, Vec3, Vec3, f64); + + fn update_skeleton( + skeleton: &Self::Skeleton, + (velocity, orientation, last_ori, global_time): Self::Dependency, + anim_time: f64, + rate: &mut f32, + skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let speed = Vec2::::from(velocity).magnitude(); + *rate = speed; + + let constant = 1.0; + let wave = (((5.0) + / (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 1.2).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * constant as f32 * 1.2).sin()); + let wave_cos = (((5.0) + / (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 2.4).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * constant as f32 * 1.5).sin()); + let wave_cos_dub = (((5.0) + / (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 4.8).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * constant as f32 * 1.5).sin()); + + let wave_diff = (anim_time as f32 * 0.6).sin(); + let wave_stop = (anim_time as f32 * 2.6).min(PI / 2.0).sin(); + let head_look = Vec2::new( + ((global_time + anim_time) as f32 / 4.0) + .floor() + .mul(7331.0) + .sin() + * 0.2, + ((global_time + anim_time) as f32 / 4.0) + .floor() + .mul(1337.0) + .sin() + * 0.1, + ); + + let ori = Vec2::from(orientation); + let last_ori = Vec2::from(last_ori); + + let tilt = if Vec2::new(ori, last_ori) + .map(|o| Vec2::::from(o).magnitude_squared()) + .map(|m| m > 0.001 && m.is_finite()) + .reduce_and() + && ori.angle_between(last_ori).is_finite() + { + ori.angle_between(last_ori).min(0.5) + * last_ori.determine_side(Vec2::zero(), ori).signum() + } else { + 0.0 + } * 1.3; + + next.head.offset = Vec3::new( + 0.0, + -3.0 + skeleton_attr.neck_forward, + skeleton_attr.neck_height + 20.0 + wave_cos * 1.3, + ); + next.head.ori = Quaternion::rotation_z(head_look.x + wave * 0.1) + * Quaternion::rotation_x(head_look.y + 0.35); + next.head.scale = Vec3::one() * skeleton_attr.head_scale; + + next.chest.offset = Vec3::new(0.0, 0.0, 7.0 + wave_cos * 1.1); + next.chest.ori = Quaternion::rotation_z(wave * 0.2); + next.chest.scale = Vec3::one(); + + next.belt.offset = Vec3::new(0.0, 0.0, 5.0 + wave_cos * 1.1); + next.belt.ori = Quaternion::rotation_z(wave * 0.35); + next.belt.scale = Vec3::one(); + + next.shorts.offset = Vec3::new(0.0, 0.0, 2.0 + wave_cos * 1.1); + next.shorts.ori = Quaternion::rotation_z(wave * 0.6); + next.shorts.scale = Vec3::one(); + + next.l_hand.offset = Vec3::new( + -6.0 + wave_stop * -1.0, + -0.25 + wave_cos * 2.0, + 5.0 - wave * 1.5, + ); + next.l_hand.ori = + Quaternion::rotation_x(0.8 + wave_cos * 1.2) * Quaternion::rotation_y(wave_stop * 0.1); + next.l_hand.scale = Vec3::one(); + + next.r_hand.offset = Vec3::new( + 6.0 + wave_stop * 1.0, + -0.25 - wave_cos * 2.0, + 5.0 + wave * 1.5, + ); + next.r_hand.ori = Quaternion::rotation_x(0.8 + wave_cos * -1.2) + * Quaternion::rotation_y(wave_stop * -0.1); + next.r_hand.scale = Vec3::one(); + + next.l_foot.offset = Vec3::new(-3.4, 0.0 + wave_cos * 1.0, 6.0 - wave_cos_dub * 0.7); + next.l_foot.ori = Quaternion::rotation_x(-0.0 - wave_cos * 1.2); + next.l_foot.scale = Vec3::one(); + + next.r_foot.offset = Vec3::new(3.4, 0.0 - wave_cos * 1.0, 6.0 - wave_cos_dub * 0.7); + next.r_foot.ori = Quaternion::rotation_x(-0.0 + wave_cos * 1.2); + next.r_foot.scale = Vec3::one(); + + next.weapon.offset = Vec3::new( + -7.0 + skeleton_attr.weapon_x, + -5.0 + skeleton_attr.weapon_y, + 15.0, + ); + next.weapon.ori = + Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57 + wave_cos * 0.25); + next.weapon.scale = Vec3::one(); + + next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7); + next.l_shoulder.ori = Quaternion::rotation_x(wave_cos * 0.15); + next.l_shoulder.scale = Vec3::one() * 1.1; + + next.r_shoulder.offset = Vec3::new(5.0, 0.0, 4.7); + next.r_shoulder.ori = Quaternion::rotation_x(wave * 0.15); + next.r_shoulder.scale = Vec3::one() * 1.1; + + next.draw.offset = Vec3::new(0.0, 5.0, 0.0); + next.draw.ori = Quaternion::rotation_y(0.0); + next.draw.scale = Vec3::one() * 0.0; + + next.torso.offset = Vec3::new(0.0, 0.3 + wave * -0.08, 0.4) * skeleton_attr.scaler; + next.torso.ori = + Quaternion::rotation_x(wave_stop * speed * -0.06 + wave_diff * speed * -0.005) + * Quaternion::rotation_y(tilt); + next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; + + next + } +} diff --git a/voxygen/src/anim/character/sneak.rs b/voxygen/src/anim/character/sneak.rs new file mode 100644 index 0000000000..389c370bb4 --- /dev/null +++ b/voxygen/src/anim/character/sneak.rs @@ -0,0 +1,151 @@ +use super::{ + super::{Animation, SkeletonAttr}, + CharacterSkeleton, +}; +use std::f32::consts::PI; +use std::ops::Mul; +use vek::*; + +pub struct SneakAnimation; + +impl Animation for SneakAnimation { + type Skeleton = CharacterSkeleton; + type Dependency = (Vec3, Vec3, Vec3, f64); + + fn update_skeleton( + skeleton: &Self::Skeleton, + (velocity, orientation, last_ori, global_time): Self::Dependency, + anim_time: f64, + rate: &mut f32, + skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let speed = Vec2::::from(velocity).magnitude(); + *rate = speed; + + let constant = 1.0; + let wave = (((5.0) + / (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 1.2).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * constant as f32 * 1.2).sin()); + let wavecos = (((5.0) + / (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 1.2).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * constant as f32 * 1.2).cos()); + let wave_cos = (((5.0) + / (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 2.4).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * constant as f32 * 1.5).sin()); + let wave_cos_dub = (((5.0) + / (1.1 + 3.9 * ((anim_time as f32 * constant as f32 * 4.8).sin()).powf(2.0 as f32))) + .sqrt()) + * ((anim_time as f32 * constant as f32 * 1.5).sin()); + let wave_slow = (anim_time as f32 * 0.1).sin(); + let wave_diff = (anim_time as f32 * 0.6).sin(); + let wave_stop = (anim_time as f32 * 2.6).min(PI / 2.0).sin(); + let head_look = Vec2::new( + ((global_time + anim_time) as f32 *0.25) + .floor() + .mul(7331.0) + .sin() + * 0.4, + ((global_time + anim_time) as f32 *0.25) + .floor() + .mul(1337.0) + .sin() + * 0.2, + ); + + let ori = Vec2::from(orientation); + let last_ori = Vec2::from(last_ori); + + let tilt = if Vec2::new(ori, last_ori) + .map(|o| Vec2::::from(o).magnitude_squared()) + .map(|m| m > 0.001 && m.is_finite()) + .reduce_and() + && ori.angle_between(last_ori).is_finite() + { + ori.angle_between(last_ori).min(0.5) + * last_ori.determine_side(Vec2::zero(), ori).signum() + } else { + 0.0 + } * 1.3; + + next.head.offset = Vec3::new( + 0.0, + 0.0 + skeleton_attr.neck_forward, + skeleton_attr.neck_height + 16.0, + ); + next.head.ori = Quaternion::rotation_z(head_look.x + wave * 0.1) + * Quaternion::rotation_x(head_look.y + 0.05); + next.head.scale = Vec3::one() * skeleton_attr.head_scale; + + next.chest.offset = Vec3::new(0.0, -1.5, 3.0 +wave_slow * 2.0); + next.chest.ori = Quaternion::rotation_x(-0.5) * Quaternion::rotation_z(wave * 0.15); + next.chest.scale = Vec3::one(); + + next.belt.offset = Vec3::new(0.0, 0.0, 1.5 + wave_cos * 0.3); + next.belt.ori = Quaternion::rotation_x(-0.1) * Quaternion::rotation_z(wave * 0.25); + next.belt.scale = Vec3::one(); + + next.shorts.offset = Vec3::new(0.0, 1.0, -1.0 + wave_cos * 0.3); + next.shorts.ori = Quaternion::rotation_x(0.2) *Quaternion::rotation_z(wave * 0.4); + next.shorts.scale = Vec3::one(); + + next.l_hand.offset = Vec3::new( + -5.0 + wave_stop * -0.5, + 2.25, + 4.0 - wave * 1.0, + ); + next.l_hand.ori = + Quaternion::rotation_x(1.5 + wave_cos * 0.1) * Quaternion::rotation_y(wave_stop * 0.1); + next.l_hand.scale = Vec3::one(); + + next.r_hand.offset = Vec3::new( + 5.0 + wave_stop * 0.5, + 2.25, + 4.0 + wave * 1.0, + ); + next.r_hand.ori = Quaternion::rotation_x(1.5 + wave_cos * -0.1) + * Quaternion::rotation_y(wave_stop * -0.1); + next.r_hand.scale = Vec3::one(); + + next.l_foot.offset = Vec3::new(-3.4, 5.0+ wave * -3.0, 4.0); + next.l_foot.ori = Quaternion::rotation_x(-0.8 + wavecos * 0.15); + next.l_foot.scale = Vec3::one(); + + next.r_foot.offset = Vec3::new(3.4, 5.0+ wave * 3.0, 4.0); + next.r_foot.ori = Quaternion::rotation_x(-0.8 - wavecos * 0.15); + next.r_foot.scale = Vec3::one(); + + next.weapon.offset = Vec3::new( + -7.0 + skeleton_attr.weapon_x, + -5.0 + skeleton_attr.weapon_y, + 15.0, + ); + next.weapon.ori = + Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57 + wave_cos * 0.25); + next.weapon.scale = Vec3::one(); + + next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7); + next.l_shoulder.ori = Quaternion::rotation_x(wavecos * 0.05); + next.l_shoulder.scale = Vec3::one() * 1.1; + + next.r_shoulder.offset = Vec3::new(5.0, 0.0, 4.7); + next.r_shoulder.ori = Quaternion::rotation_x(wave * 0.05); + next.r_shoulder.scale = Vec3::one() * 1.1; + + next.draw.offset = Vec3::new(0.0, 5.0, 0.0); + next.draw.ori = Quaternion::rotation_y(0.0); + next.draw.scale = Vec3::one() * 0.0; + + next.torso.offset = Vec3::new(0.0, 0.3 + wave * -0.08, 0.4) * skeleton_attr.scaler; + next.torso.ori = + Quaternion::rotation_x(wave_stop * speed * -0.03 + wave_diff * speed * -0.005) + * Quaternion::rotation_y(tilt); + next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler; + + next + } +} diff --git a/voxygen/src/anim/fishmedium/idle.rs b/voxygen/src/anim/fishmedium/idle.rs new file mode 100644 index 0000000000..2b04526f34 --- /dev/null +++ b/voxygen/src/anim/fishmedium/idle.rs @@ -0,0 +1,70 @@ +use super::{ + super::{Animation, SkeletonAttr}, + FishMediumSkeleton, +}; +use std::{f32::consts::PI, ops::Mul}; +use vek::*; + +pub struct IdleAnimation; + +impl Animation for IdleAnimation { + type Skeleton = FishMediumSkeleton; + type Dependency = (f64); + + fn update_skeleton( + skeleton: &Self::Skeleton, + global_time: Self::Dependency, + anim_time: f64, + _rate: &mut f32, + _skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin(); + let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos(); + let wave_slow = (anim_time as f32 * 3.5 + PI).sin(); + let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos(); + + let duck_m_look = Vec2::new( + ((global_time + anim_time) as f32 / 8.0) + .floor() + .mul(7331.0) + .sin() + * 0.5, + ((global_time + anim_time) as f32 / 8.0) + .floor() + .mul(1337.0) + .sin() + * 0.25, + ); + + + next.marlin_head.offset = Vec3::new(0.0, 7.5, 15.0) / 11.0; + next.marlin_head.ori = + Quaternion::rotation_z(duck_m_look.x) * Quaternion::rotation_x(duck_m_look.y); + next.marlin_head.scale = Vec3::one() / 10.88; + + next.marlin_torso.offset = + Vec3::new(0.0, 4.5 - wave_ultra_slow_cos * 0.12, 2.0); + next.marlin_torso.ori = Quaternion::rotation_x(0.0); + next.marlin_torso.scale = Vec3::one() * 1.01; + + next.marlin_rear.offset = Vec3::new(0.0, 3.1, -4.5); + next.marlin_rear.ori = Quaternion::rotation_z(0.0); + next.marlin_rear.scale = Vec3::one() * 0.98; + + next.marlin_tail.offset = Vec3::new(0.0, -13.0, 8.0) / 11.0; + next.marlin_tail.ori = Quaternion::rotation_z(0.0) + * Quaternion::rotation_x(0.0); + next.marlin_tail.scale = Vec3::one() / 11.0; + + next.marlin_fin_l.offset = Vec3::new(0.0, -11.7, 11.0) / 11.0; + next.marlin_fin_l.ori = Quaternion::rotation_y(0.0); + next.marlin_fin_l.scale = Vec3::one() / 11.0; + + next.marlin_fin_r.offset = Vec3::new(0.0, 0.0, 12.0) / 11.0; + next.marlin_fin_r.ori = Quaternion::rotation_y(0.0); + next.marlin_fin_r.scale = Vec3::one() / 10.5; + next + } +} diff --git a/voxygen/src/anim/fishmedium/jump.rs b/voxygen/src/anim/fishmedium/jump.rs new file mode 100644 index 0000000000..cb817e502b --- /dev/null +++ b/voxygen/src/anim/fishmedium/jump.rs @@ -0,0 +1,58 @@ +use super::{ + super::{Animation, SkeletonAttr}, + FishMediumSkeleton, +}; +use std::f32::consts::PI; +use vek::*; + +pub struct JumpAnimation; + +impl Animation for JumpAnimation { + type Skeleton = FishMediumSkeleton; + type Dependency = (f32, f64); + + fn update_skeleton( + skeleton: &Self::Skeleton, + global_time: Self::Dependency, + anim_time: f64, + _rate: &mut f32, + _skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin(); + let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos(); + let wave_slow = (anim_time as f32 * 3.5 + PI).sin(); + let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos(); + + + + next.marlin_head.offset = Vec3::new(0.0, 7.5, 15.0) / 11.0; + next.marlin_head.ori = + Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0); + next.marlin_head.scale = Vec3::one() / 10.88; + + next.marlin_torso.offset = + Vec3::new(0.0, 4.5 - wave_ultra_slow_cos * 0.12, 2.0); + next.marlin_torso.ori = Quaternion::rotation_x(0.0); + next.marlin_torso.scale = Vec3::one() * 1.01; + + next.marlin_rear.offset = Vec3::new(0.0, 3.1, -4.5); + next.marlin_rear.ori = Quaternion::rotation_z(0.0); + next.marlin_rear.scale = Vec3::one() * 0.98; + + next.marlin_tail.offset = Vec3::new(0.0, -13.0, 8.0) / 11.0; + next.marlin_tail.ori = Quaternion::rotation_z(0.0) + * Quaternion::rotation_x(0.0); + next.marlin_tail.scale = Vec3::one() / 11.0; + + next.marlin_fin_l.offset = Vec3::new(0.0, -11.7, 11.0) / 11.0; + next.marlin_fin_l.ori = Quaternion::rotation_y(0.0); + next.marlin_fin_l.scale = Vec3::one() / 11.0; + + next.marlin_fin_r.offset = Vec3::new(0.0, 0.0, 12.0) / 11.0; + next.marlin_fin_r.ori = Quaternion::rotation_y(0.0); + next.marlin_fin_r.scale = Vec3::one() / 10.5; + next + } +} diff --git a/voxygen/src/anim/fishmedium/mod.rs b/voxygen/src/anim/fishmedium/mod.rs new file mode 100644 index 0000000000..6689dbea3a --- /dev/null +++ b/voxygen/src/anim/fishmedium/mod.rs @@ -0,0 +1,77 @@ +pub mod idle; +pub mod jump; +pub mod run; + +// Reexports +pub use self::idle::IdleAnimation; +pub use self::jump::JumpAnimation; +pub use self::run::RunAnimation; + +use super::{Bone, Skeleton}; +use crate::render::FigureBoneData; + +#[derive(Clone)] +pub struct FishMediumSkeleton { + marlin_head: Bone, + marlin_torso: Bone, + marlin_rear: Bone, + marlin_tail: Bone, + marlin_fin_l: Bone, + marlin_fin_r: Bone, + +} + +impl FishMediumSkeleton { + pub fn new() -> Self { + Self { + marlin_head: Bone::default(), + marlin_torso: Bone::default(), + marlin_rear: Bone::default(), + marlin_tail: Bone::default(), + marlin_fin_l: Bone::default(), + marlin_fin_r: Bone::default(), + + } + } +} + +impl Skeleton for FishMediumSkeleton { + fn compute_matrices(&self) -> [FigureBoneData; 16] { + let torso_mat = self.marlin_torso.compute_base_matrix(); + let rear_mat = self.marlin_rear.compute_base_matrix(); + + + [ + FigureBoneData::new(self.marlin_head.compute_base_matrix() * torso_mat), + FigureBoneData::new( + torso_mat, + ), + FigureBoneData::new(rear_mat * torso_mat), + FigureBoneData::new(self.marlin_tail.compute_base_matrix() * rear_mat), + FigureBoneData::new(self.marlin_fin_l.compute_base_matrix() * rear_mat), + FigureBoneData::new(self.marlin_fin_r.compute_base_matrix() * rear_mat), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + FigureBoneData::default(), + ] + } + + fn interpolate(&mut self, target: &Self, dt: f32) { + self.marlin_head + .interpolate(&target.marlin_head, dt); + self.marlin_torso.interpolate(&target.marlin_torso, dt); + self.marlin_rear + .interpolate(&target.marlin_rear, dt); + self.marlin_tail.interpolate(&target.marlin_tail, dt); + self.marlin_fin_l + .interpolate(&target.marlin_fin_l, dt); + self.marlin_fin_r.interpolate(&target.marlin_fin_r, dt); + } +} diff --git a/voxygen/src/anim/fishmedium/run.rs b/voxygen/src/anim/fishmedium/run.rs new file mode 100644 index 0000000000..0f1e92743f --- /dev/null +++ b/voxygen/src/anim/fishmedium/run.rs @@ -0,0 +1,58 @@ +use super::{ + super::{Animation, SkeletonAttr}, + FishMediumSkeleton, +}; +use std::{f32::consts::PI}; +use vek::*; + +pub struct RunAnimation; + +impl Animation for RunAnimation { + type Skeleton = FishMediumSkeleton; + type Dependency = (f32, f64); + + fn update_skeleton( + skeleton: &Self::Skeleton, + global_time: Self::Dependency, + anim_time: f64, + _rate: &mut f32, + _skeleton_attr: &SkeletonAttr, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + + let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin(); + let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos(); + let wave_slow = (anim_time as f32 * 3.5 + PI).sin(); + let wave_slow_cos = (anim_time as f32 * 3.5 + PI).cos(); + + + + next.marlin_head.offset = Vec3::new(0.0, 7.5, 15.0) / 11.0; + next.marlin_head.ori = + Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0); + next.marlin_head.scale = Vec3::one() / 10.88; + + next.marlin_torso.offset = + Vec3::new(0.0, 4.5 - wave_ultra_slow_cos * 0.12, 2.0); + next.marlin_torso.ori = Quaternion::rotation_x(0.0); + next.marlin_torso.scale = Vec3::one() * 1.01; + + next.marlin_rear.offset = Vec3::new(0.0, 3.1, -4.5); + next.marlin_rear.ori = Quaternion::rotation_z(0.0); + next.marlin_rear.scale = Vec3::one() * 0.98; + + next.marlin_tail.offset = Vec3::new(0.0, -13.0, 8.0) / 11.0; + next.marlin_tail.ori = Quaternion::rotation_z(0.0) + * Quaternion::rotation_x(0.0); + next.marlin_tail.scale = Vec3::one() / 11.0; + + next.marlin_fin_l.offset = Vec3::new(0.0, -11.7, 11.0) / 11.0; + next.marlin_fin_l.ori = Quaternion::rotation_y(0.0); + next.marlin_fin_l.scale = Vec3::one() / 11.0; + + next.marlin_fin_r.offset = Vec3::new(0.0, 0.0, 12.0) / 11.0; + next.marlin_fin_r.ori = Quaternion::rotation_y(0.0); + next.marlin_fin_r.scale = Vec3::one() / 10.5; + next + } +} diff --git a/voxygen/src/anim/mod.rs b/voxygen/src/anim/mod.rs index a527d759ce..b9600a531a 100644 --- a/voxygen/src/anim/mod.rs +++ b/voxygen/src/anim/mod.rs @@ -3,6 +3,8 @@ pub mod fixture; pub mod object; pub mod quadruped; pub mod quadrupedmedium; +pub mod birdmedium; +pub mod fishmedium; use crate::render::FigureBoneData; use common::comp::{self, item::Tool}; diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index 5063b50a14..9c89226f2a 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -226,6 +226,42 @@ impl FigureModelCache { None, None, ], + Body::BirdMedium(body) => [ + Some(mesh_duck_m_head(body.head)), + Some(mesh_duck_m_torso(body.torso)), + Some(mesh_duck_m_tail(body.tail)), + Some(mesh_duck_m_wing_l(body.wing_l)), + Some(mesh_duck_m_wing_r(body.wing_r)), + Some(mesh_duck_m_leg_l(body.leg_l)), + Some(mesh_duck_m_leg_r(body.leg_r)), + None, + None, + None, + None, + None, + None, + None, + None, + None, + ], + Body::FishMedium(body) => [ + Some(mesh_marlin_head(body.head)), + Some(mesh_marlin_torso(body.torso)), + Some(mesh_marlin_rear(body.rear)), + Some(mesh_marlin_tail(body.tail)), + Some(mesh_marlin_fin_l(body.fin_l)), + Some(mesh_marlin_fin_r(body.fin_r)), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + ], Body::Object(object) => [ Some(mesh_object(object)), None, diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index b5783de10c..20ed90280c 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -10,7 +10,7 @@ use common::{ Belt, BodyType, Chest, EyeColor, Eyebrows, Foot, Hand, Pants, Race, Shoulder, Skin, }, item::Tool, - object, quadruped, quadruped_medium, Item, ItemKind, + object, quadruped, quadruped_medium, bird_medium, fish_medium, Item, Itemkind }, figure::{DynaUnionizer, MatSegment, Material, Segment}, }; @@ -697,7 +697,124 @@ pub fn mesh_wolf_foot_rb(foot_rb: quadruped_medium::FootRB) -> Mesh Mesh { + load_mesh( + match head { + bird_medium::Head::Default => "npc.duck_m.duck_m_head", + }, + Vec3::new(-7.0, -6.0, -6.0), + ) +} +pub fn mesh_duck_m_torso(torso: bird_medium::Torso) -> Mesh { + load_mesh( + match torso { + bird_medium::Torso::Default => "npc.duck_m.duck_m_body", + }, + Vec3::new(-8.0, -5.5, -6.0), + ) +} + +pub fn mesh_duck_m_tail(tail: bird_medium::Tail) -> Mesh { + load_mesh( + match tail { + bird_medium::Tail::Default => "npc.duck_m.duck_m_tail", + }, + Vec3::new(-4.0, -1.0, -1.0), + ) +} + +pub fn mesh_duck_m_wing_l(wing_l: bird_medium::WingL) -> Mesh { + load_mesh( + match wing_l { + bird_medium::WingL::Default => "npc.duck_m.duck_m_wing", + }, + Vec3::new(-2.5, -4.0, -2.5), + ) +} + +pub fn mesh_duck_m_wing_r(wing_r: bird_medium::WingR) -> Mesh { + load_mesh( + match wing_r { + bird_medium::WingR::Default => "npc.duck_m.duck_m_wing", + }, + Vec3::new(-2.5, -4.0, -2.5), + ) +} + +pub fn mesh_duck_m_leg_l(leg_l: bird_medium::LegL) -> Mesh { + load_mesh( + match leg_l { + bird_medium::LegL::Default => "npc.duck_m.duck_m_leg_l", + }, + Vec3::new(-2.5, -4.0, -2.5), + ) +} + +pub fn mesh_duck_m_leg_r(leg_r: bird_medium::LegR) -> Mesh { + load_mesh( + match leg_r { + bird_medium::LegR::Default => "npc.duck_m.duck_m_leg_r", + }, + Vec3::new(-2.5, -4.0, -2.5), + ) +} +//// +pub fn mesh_marlin_head(head: fish_medium::Head) -> Mesh { + load_mesh( + match head { + fish_medium::Head::Default => "npc.marlin.marlin_head", + }, + Vec3::new(-7.0, -6.0, -6.0), + ) +} + +pub fn mesh_marlin_torso(torso: fish_medium::Torso) -> Mesh { + load_mesh( + match torso { + fish_medium::Torso::Default => "npc.marlin.marlin_torso", + }, + Vec3::new(-7.0, -6.0, -6.0), + ) +} + +pub fn mesh_marlin_rear(rear: fish_medium::Rear) -> Mesh { + load_mesh( + match rear { + fish_medium::Rear::Default => "npc.marlin.marlin_rear", + }, + Vec3::new(-7.0, -6.0, -6.0), + ) +} + +pub fn mesh_marlin_tail(tail: fish_medium::Tail) -> Mesh { + load_mesh( + match tail { + fish_medium::Tail::Default => "npc.marlin.marlin_tail", + }, + Vec3::new(-7.0, -6.0, -6.0), + ) +} + +pub fn mesh_marlin_fin_l(fin_l: fish_medium::FinL) -> Mesh { + load_mesh( + match fin_l { + fish_medium::FinL::Default => "npc.marlin.marlin_fin_l", + }, + Vec3::new(-7.0, -6.0, -6.0), + ) +} + +pub fn mesh_marlin_fin_r(fin_r: fish_medium::FinR) -> Mesh { + load_mesh( + match fin_r { + fish_medium::FinR::Default => "npc.marlin.marlin_fin_r", + }, + Vec3::new(-7.0, -6.0, -6.0), + ) +} +//// pub fn mesh_object(obj: object::Body) -> Mesh { use object::Body; diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index ef0b35f046..3c87e24ffd 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -7,7 +7,7 @@ pub use load::load_mesh; // TODO: Don't make this public. use crate::{ anim::{ self, character::CharacterSkeleton, object::ObjectSkeleton, quadruped::QuadrupedSkeleton, - quadrupedmedium::QuadrupedMediumSkeleton, Animation, Skeleton, + quadrupedmedium::QuadrupedMediumSkeleton, birdmedium::BirdMediumSkeleton, fishmedium::FishMediumSkeleton,Animation, Skeleton, }, render::{Consts, FigureBoneData, FigureLocals, Globals, Light, Renderer, Shadow}, scene::camera::{Camera, CameraMode}, @@ -32,6 +32,8 @@ pub struct FigureMgr { character_states: HashMap>, quadruped_states: HashMap>, quadruped_medium_states: HashMap>, + bird_medium_states: HashMap>, + fish_medium_states: HashMap>, object_states: HashMap>, } @@ -42,6 +44,8 @@ impl FigureMgr { character_states: HashMap::new(), quadruped_states: HashMap::new(), quadruped_medium_states: HashMap::new(), + bird_medium_states: HashMap::new(), + fish_medium_states: HashMap::new(), object_states: HashMap::new(), } } @@ -93,6 +97,12 @@ impl FigureMgr { Body::QuadrupedMedium(_) => { self.quadruped_medium_states.remove(&entity); } + Body::BirdMedium(_) => { + self.bird_medium_states.remove(&entity); + } + Body::FishMedium(_) => { + self.fish_medium_states.remove(&entity); + } Body::Object(_) => { self.object_states.remove(&entity); } @@ -378,6 +388,120 @@ impl FigureMgr { action_animation_rate, ); } + Body::BirdMedium(_) => { + let state = self + .bird_medium_states + .entry(entity) + .or_insert_with(|| { + FigureState::new(renderer, BirdMediumSkeleton::new()) + }); + + let (character, last_character) = match (character, last_character) { + (Some(c), Some(l)) => (c, l), + _ => continue, + }; + + if !character.is_same_movement(&last_character.0) { + state.movement_time = 0.0; + } + + let target_base = match character.movement { + Stand => anim::birdmedium::IdleAnimation::update_skeleton( + &BirdMediumSkeleton::new(), + time, + state.movement_time, + &mut movement_animation_rate, + skeleton_attr, + ), + Run => anim::birdmedium::RunAnimation::update_skeleton( + &BirdMediumSkeleton::new(), + (vel.0.magnitude(), time), + state.movement_time, + &mut movement_animation_rate, + skeleton_attr, + ), + Jump => anim::birdmedium::JumpAnimation::update_skeleton( + &BirdMediumSkeleton::new(), + (vel.0.magnitude(), time), + state.movement_time, + &mut movement_animation_rate, + skeleton_attr, + ), + + // TODO! + _ => state.skeleton_mut().clone(), + }; + + state.skeleton.interpolate(&target_base, dt); + state.update( + renderer, + pos.0, + vel.0, + ori.0, + scale, + col, + dt, + movement_animation_rate, + action_animation_rate, + ); + } + Body::FishMedium(_) => { + let state = self + .fish_medium_states + .entry(entity) + .or_insert_with(|| { + FigureState::new(renderer, FishMediumSkeleton::new()) + }); + + let (character, last_character) = match (character, last_character) { + (Some(c), Some(l)) => (c, l), + _ => continue, + }; + + if !character.is_same_movement(&last_character.0) { + state.movement_time = 0.0; + } + + let target_base = match character.movement { + Stand => anim::fishmedium::IdleAnimation::update_skeleton( + &FishMediumSkeleton::new(), + time, + state.movement_time, + &mut movement_animation_rate, + skeleton_attr, + ), + Run => anim::fishmedium::RunAnimation::update_skeleton( + &FishMediumSkeleton::new(), + (vel.0.magnitude(), time), + state.movement_time, + &mut movement_animation_rate, + skeleton_attr, + ), + Jump => anim::fishmedium::JumpAnimation::update_skeleton( + &FishMediumSkeleton::new(), + (vel.0.magnitude(), time), + state.movement_time, + &mut movement_animation_rate, + skeleton_attr, + ), + + // TODO! + _ => state.skeleton_mut().clone(), + }; + + state.skeleton.interpolate(&target_base, dt); + state.update( + renderer, + pos.0, + vel.0, + ori.0, + scale, + col, + dt, + movement_animation_rate, + action_animation_rate, + ); + } Body::Object(_) => { let state = self .object_states @@ -407,6 +531,10 @@ impl FigureMgr { .retain(|entity, _| ecs.entities().is_alive(*entity)); self.quadruped_medium_states .retain(|entity, _| ecs.entities().is_alive(*entity)); + self.bird_medium_states + .retain(|entity, _| ecs.entities().is_alive(*entity)); + self.fish_medium_states + .retain(|entity, _| ecs.entities().is_alive(*entity)); self.object_states .retain(|entity, _| ecs.entities().is_alive(*entity)); } @@ -464,6 +592,14 @@ impl FigureMgr { .quadruped_medium_states .get(&entity) .map(|state| (state.locals(), state.bone_consts())), + Body::BirdMedium(_) => self + .bird_medium_states + .get(&entity) + .map(|state| (state.locals(), state.bone_consts())), + Body::FishMedium(_) => self + .fish_medium_states + .get(&entity) + .map(|state| (state.locals(), state.bone_consts())), Body::Object(_) => self .object_states .get(&entity)