From fa6f9136600be0d1c751a9e50521df46171e8fef Mon Sep 17 00:00:00 2001 From: jshipsey Date: Thu, 16 May 2019 00:40:35 -0400 Subject: [PATCH] glide anim Former-commit-id: b614a672b0a94f2b8803c0c1c22468b889242cc6 --- assets/voxygen/voxel/glider.vox | Bin 0 -> 9040 bytes common/src/comp/actor.rs | 1 + common/src/sys/control.rs | 2 +- voxygen/src/anim/character/gliding.rs | 105 +++++++++++++++++++++++++ voxygen/src/anim/character/idle.rs | 6 +- voxygen/src/anim/character/jump.rs | 3 + voxygen/src/anim/character/mod.rs | 11 ++- voxygen/src/anim/character/run.rs | 6 +- voxygen/src/anim/quadruped/jump.rs | 2 +- voxygen/src/menu/char_selection/mod.rs | 2 +- voxygen/src/scene/figure.rs | 32 +++++--- 11 files changed, 144 insertions(+), 26 deletions(-) create mode 100644 assets/voxygen/voxel/glider.vox create mode 100644 voxygen/src/anim/character/gliding.rs diff --git a/assets/voxygen/voxel/glider.vox b/assets/voxygen/voxel/glider.vox new file mode 100644 index 0000000000000000000000000000000000000000..39f2f1cb9905fd506e44a924e002d94f8f72e3e6 GIT binary patch literal 9040 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 literal 0 HcmV?d00001 diff --git a/common/src/comp/actor.rs b/common/src/comp/actor.rs index 5772350fa8..eca896ee17 100644 --- a/common/src/comp/actor.rs +++ b/common/src/comp/actor.rs @@ -223,6 +223,7 @@ pub enum Animation { Idle, Run, Jump, + Gliding, } impl Component for AnimationHistory { diff --git a/common/src/sys/control.rs b/common/src/sys/control.rs index 7c1f41ce91..d84d50c410 100644 --- a/common/src/sys/control.rs +++ b/common/src/sys/control.rs @@ -81,7 +81,7 @@ impl<'a> System<'a> for Sys { Animation::Idle } } else { - Animation::Jump + Animation::Gliding }; let last_history = anims.get_mut(entity).cloned(); diff --git a/voxygen/src/anim/character/gliding.rs b/voxygen/src/anim/character/gliding.rs new file mode 100644 index 0000000000..19ebfbece8 --- /dev/null +++ b/voxygen/src/anim/character/gliding.rs @@ -0,0 +1,105 @@ +// Standard +use std::{f32::consts::PI, ops::Mul}; + +// Library +use vek::*; + +// Local +use super::{super::Animation, CharacterSkeleton, SCALE}; +// + +pub struct GlidingAnimation; + +impl Animation for GlidingAnimation { + type Skeleton = CharacterSkeleton; + type Dependency = f64; + + fn update_skeleton( + skeleton: &Self::Skeleton, + global_time: f64, + anim_time: f64, + ) -> Self::Skeleton { + let mut next = (*skeleton).clone(); + let wave = (anim_time as f32 * 14.0).sin(); + let waveslow = (anim_time as f32 * 7.0).sin(); + let wavecos_slow = (anim_time as f32 * 7.0).cos(); + let arcwave = (1.0f32.ln_1p() - 1.5).abs(); + let wavetest = (wave.cbrt()); + let fuzzwave = (anim_time as f32 * 12.0).sin(); + let wavecos = (anim_time as f32 * 14.0).cos(); + let wave_stop = (anim_time as f32 * 1.5).min(PI / 2.0).sin(); + let wave_stopalt = (anim_time as f32 * 5.0).min(PI / 2.0).sin(); + let waveveryslow = (anim_time as f32 * 3.0).sin(); + let waveveryslowalt = (anim_time as f32 * 2.5).sin(); + let waveveryslowcos = (anim_time as f32 * 3.0).cos(); + + + let wave_slowtest = (anim_time as f32).min(PI / 2.0).sin(); + + let head_look = Vec2::new( + ((global_time + anim_time) as f32 / 4.0) + .floor() + .mul(7331.0) + .sin() + * 0.5, + ((global_time + anim_time) as f32 / 4.0) + .floor() + .mul(1337.0) + .sin() + * 0.25, + ); + next.head.offset = Vec3::new(5.5, 2.0, 12.0); + next.head.ori = Quaternion::rotation_x(0.35 - waveveryslow * 0.10 + head_look.y) * Quaternion::rotation_z(head_look.x + waveveryslowcos * 0.15); + next.head.scale = Vec3::one(); + + next.chest.offset = Vec3::new(5.5, 0.0, 8.0); + next.chest.ori = Quaternion::rotation_z(waveveryslowcos * 0.15); + next.chest.scale = Vec3::one(); + + next.belt.offset = Vec3::new(5.5, 0.0, 6.0); + next.belt.ori = Quaternion::rotation_z(waveveryslowcos * 0.20); + next.belt.scale = Vec3::one(); + + next.shorts.offset = Vec3::new(5.5, 0.0, 3.0); + next.shorts.ori = Quaternion::rotation_z(waveveryslowcos * 0.25); + next.shorts.scale = Vec3::one(); + + next.l_hand.offset = Vec3::new(-8.0, -10.0 + waveveryslow * 2.5, 18.5 + waveveryslow * 1.0); + next.l_hand.ori = Quaternion::rotation_x(0.9 - waveveryslow * 0.10); + next.l_hand.scale = Vec3::one(); + + next.r_hand.offset = Vec3::new(11.0, -10.0 + waveveryslow * 2.5, 18.5 + waveveryslow * 1.0); + next.r_hand.ori = Quaternion::rotation_x(0.9 - waveveryslow * 0.10); + next.r_hand.scale = Vec3::one(); + + next.l_foot.offset = Vec3::new(-3.4, 1.0, 8.0); + next.l_foot.ori = Quaternion::rotation_x(wave_stop * -0.7 - wavecos_slow * -0.21 + waveveryslow * 0.19); + next.l_foot.scale = Vec3::one(); + + next.r_foot.offset = Vec3::new(3.4, 1.0, 8.0); + next.r_foot.ori = Quaternion::rotation_x(wave_stop * -0.8 + waveslow * -0.25 + waveveryslowalt * 0.13); + next.r_foot.scale = Vec3::one(); + + next.weapon.offset = Vec3::new(-5.0, -6.0, 19.0); + next.weapon.ori = Quaternion::rotation_y(2.5); + next.weapon.scale = Vec3::one(); + + next.l_shoulder.offset = Vec3::new(-10.0, -3.0, 2.5); + next.l_shoulder.ori = Quaternion::rotation_x(0.0); + next.l_shoulder.scale = Vec3::one(); + + next.r_shoulder.offset = Vec3::new(0.0, -3.0, 2.5); + next.r_shoulder.ori = Quaternion::rotation_x(0.0); + next.r_shoulder.scale = Vec3::one(); + + next.torso.offset = Vec3::new(-0.5, -0.2, 0.0); + next.torso.ori = Quaternion::rotation_x(-0.8 + waveveryslow * 0.10); + next.torso.scale = Vec3::one() / 11.0; + + next.draw.offset = Vec3::new(13.5, 3.0, -1.0); + next.draw.ori = Quaternion::rotation_y(waveveryslowcos * 0.05); + next.draw.scale = Vec3::one(); + + next + } +} diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index 1a629d3b0b..bef3f44247 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -100,9 +100,9 @@ impl Animation for IdleAnimation { next.torso.ori = Quaternion::rotation_x(0.0); next.torso.scale = Vec3::one() / 11.0; - next.draw.offset = Vec3::new(0.0, 1.0, -8.0); - next.draw.ori = Quaternion::rotation_y(-0.2); - next.draw.scale = Vec3::one(); + next.draw.offset = Vec3::new(0.0, 0.0, 0.0); + next.draw.ori = Quaternion::rotation_y(0.0); + next.draw.scale = Vec3::one() * 0.0; next } } diff --git a/voxygen/src/anim/character/jump.rs b/voxygen/src/anim/character/jump.rs index acbd79adb0..ffcbf8b718 100644 --- a/voxygen/src/anim/character/jump.rs +++ b/voxygen/src/anim/character/jump.rs @@ -80,6 +80,9 @@ impl Animation for JumpAnimation { next.torso.ori = Quaternion::rotation_x(-0.2); next.torso.scale = Vec3::one() / 11.0; + next.draw.offset = Vec3::new(0.0, 0.0, 0.0); + next.draw.ori = Quaternion::rotation_y(0.0); + next.draw.scale = Vec3::one() * 0.0; next } } diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 8a348ce769..3605286cfc 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -1,11 +1,14 @@ pub mod idle; pub mod jump; pub mod run; +pub mod gliding; + // Reexports pub use self::idle::IdleAnimation; pub use self::jump::JumpAnimation; pub use self::run::RunAnimation; +pub use self::gliding::GlidingAnimation; // Crate use crate::render::FigureBoneData; @@ -27,8 +30,8 @@ pub struct CharacterSkeleton { weapon: Bone, l_shoulder: Bone, r_shoulder: Bone, - torso: Bone, draw: Bone, + torso: Bone, } impl CharacterSkeleton { @@ -45,8 +48,8 @@ impl CharacterSkeleton { weapon: Bone::default(), l_shoulder: Bone::default(), r_shoulder: Bone::default(), - torso: Bone::default(), draw: Bone::default(), + torso: Bone::default(), } } } @@ -68,8 +71,8 @@ impl Skeleton for CharacterSkeleton { FigureBoneData::new(torso_mat * chest_mat * self.weapon.compute_base_matrix()), FigureBoneData::new(torso_mat * chest_mat * self.l_shoulder.compute_base_matrix()), FigureBoneData::new(torso_mat * chest_mat * self.r_shoulder.compute_base_matrix()), - FigureBoneData::new(torso_mat), FigureBoneData::new(torso_mat * l_hand_mat * self.draw.compute_base_matrix()), + FigureBoneData::new(torso_mat), FigureBoneData::default(), FigureBoneData::default(), FigureBoneData::default(), @@ -88,7 +91,7 @@ impl Skeleton for CharacterSkeleton { self.weapon.interpolate(&target.weapon); self.l_shoulder.interpolate(&target.l_shoulder); self.r_shoulder.interpolate(&target.r_shoulder); - self.torso.interpolate(&target.torso); self.draw.interpolate(&target.draw); + self.torso.interpolate(&target.torso); } } diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index 22b738e27c..f0c6d733a1 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -76,9 +76,9 @@ impl Animation for RunAnimation { next.torso.ori = Quaternion::rotation_x(-velocity * 0.05 - wavecos * 0.1); next.torso.scale = Vec3::one() / 11.0; - next.draw.offset = Vec3::new(0.0, 1.0, -8.0); - next.draw.ori = Quaternion::rotation_y(-0.2); - next.draw.scale = Vec3::one(); + next.draw.offset = Vec3::new(0.0, 0.0, 0.0); + next.draw.ori = Quaternion::rotation_y(0.0); + next.draw.scale = Vec3::one() * 0.0; next } diff --git a/voxygen/src/anim/quadruped/jump.rs b/voxygen/src/anim/quadruped/jump.rs index a8724c7ce2..9d25f69d3e 100644 --- a/voxygen/src/anim/quadruped/jump.rs +++ b/voxygen/src/anim/quadruped/jump.rs @@ -39,7 +39,7 @@ impl Animation for JumpAnimation { next.pigchest.scale = Vec3::one() / 11.0; next.piglf_leg.offset = Vec3::new(-4.5, 3.0, 1.5) / 11.0; - next.piglf_leg.ori = Quaternion::rotation_x(wave_stop * 0.6); + next.piglf_leg.ori = Quaternion::rotation_x(wave_stop * 0.6 - wave_slow * 0.3); next.piglf_leg.scale = Vec3::one() / 11.0; next.pigrf_leg.offset = Vec3::new(2.5, 3.0, 1.5) / 11.0; diff --git a/voxygen/src/menu/char_selection/mod.rs b/voxygen/src/menu/char_selection/mod.rs index cbe77c7d6e..e1b86311da 100644 --- a/voxygen/src/menu/char_selection/mod.rs +++ b/voxygen/src/menu/char_selection/mod.rs @@ -82,7 +82,7 @@ impl PlayState for CharSelectionState { .postbox .send_message(ClientMsg::Character { name: self.char_selection_ui.character_name.clone(), - body: comp::Body::Quadruped(comp::QuadrupedBody::random()), // comp::Body::Humanoid(self.char_selection_ui.character_body), + body: comp::Body::Humanoid(self.char_selection_ui.character_body), //body: comp::Body::Quadruped(comp::QuadrupedBody::random()), }); return PlayStateResult::Switch(Box::new(SessionState::new( &mut global_state.window, diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index d4e98dee22..3c771579dc 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -15,7 +15,7 @@ use common::{ assets, comp::{ self, - actor::{Belt, Chest, Foot, Hand, Head, Pants, Shoulder, Weapon, Pighead, Pigchest, Pigleg_l, Pigleg_r}, + actor::{Belt, Chest, Foot, Hand, Head, Pants, Shoulder, Weapon, Draw, Pighead, Pigchest, Pigleg_l, Pigleg_r}, Body, HumanoidBody, QuadrupedBody }, figure::Segment, @@ -65,7 +65,7 @@ impl FigureModelCache { Some(Self::load_weapon(body.weapon)), Some(Self::load_left_shoulder(body.shoulder)), Some(Self::load_right_shoulder(body.shoulder)), - None, + Some(Self::load_draw(body.draw)), None, None, None, @@ -226,17 +226,17 @@ impl FigureModelCache { Vec3::new(2.5, 0.0, 0.0), ) } - // fn load_draw(draw: Draw) -> Mesh { - // Self::load_mesh( - // match draw { - // //Draw::DefaultDraw => "sword.vox", - // - // }, - // Vec3::new(0.0, 0.0, -2.0) - // - // - // ) - // } + fn load_draw(draw: Draw) -> Mesh { + Self::load_mesh( + match draw { + Draw::Default => "glider.vox", + + }, + Vec3::new(-26.0, -26.0, -5.0) + + + ) + } fn load_pighead(pighead: Pighead) -> Mesh { Self::load_mesh( @@ -350,6 +350,11 @@ impl FigureMgr { time, animation_history.time, ), + comp::Animation::Gliding => character::GlidingAnimation::update_skeleton( + state.skeleton_mut(), + time, + animation_history.time, + ), }; state.skeleton.interpolate(&target_skeleton); @@ -377,6 +382,7 @@ impl FigureMgr { (vel.0.magnitude(), time), animation_history.time, ), + // TODO! _ => state.skeleton_mut().clone(), };