diff --git a/assets/voxygen/voxel/biped_large_center_manifest.ron b/assets/voxygen/voxel/biped_large_center_manifest.ron index 55fc0ecc34..c1a154eab9 100644 --- a/assets/voxygen/voxel/biped_large_center_manifest.ron +++ b/assets/voxygen/voxel/biped_large_center_manifest.ron @@ -12,6 +12,18 @@ offset: (-5.0, -4.5, -9.0), center: ("npc.ogre.male.torso_lower"), ), + jaw: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-8.0, -4.5, -5.0), center: ("armor.empty"), @@ -30,6 +42,18 @@ offset: (-5.0, -4.5, -9.0), center: ("npc.ogre.male.torso_lower"), ), + jaw: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-8.0, -4.5, -5.0), center: ("armor.empty"), @@ -48,6 +72,18 @@ offset: (-6.0, -5.5, -12.0), center: ("npc.cyclops.male.torso_lower"), ), + jaw: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-5.0, -6.5, -4.0), center: ("npc.cyclops.male.hammer"), @@ -66,6 +102,18 @@ offset: (-6.0, -5.5, -12.0), center: ("npc.cyclops.male.torso_lower"), ), + jaw: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-5.0, -6.5, -4.0), center: ("npc.cyclops.male.hammer"), @@ -84,6 +132,18 @@ offset: (-4.0, -2.0, -4.0), center: ("npc.wendigo.male.torso_lower"), ), + jaw: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-8.0, -4.5, -5.0), center: ("armor.empty"), @@ -102,6 +162,18 @@ offset: (-4.0, -2.0, -4.0), center: ("npc.wendigo.male.torso_lower"), ), + jaw: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-8.0, -4.5, -5.0), center: ("armor.empty"), @@ -120,6 +192,18 @@ offset: (-6.0, -3.5, -5.0), center: ("npc.troll.male.torso_lower"), ), + jaw: ( + offset: (-4.0, 0.0, -4.5), + center: ("npc.troll.male.jaw"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-8.0, -4.5, -5.0), center: ("armor.empty"), @@ -138,6 +222,18 @@ offset: (-6.0, -3.5, -5.0), center: ("npc.troll.male.torso_lower"), ), + jaw: ( + offset: (-4.0, 0.0, -4.5), + center: ("npc.troll.male.jaw"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-8.0, -4.5, -5.0), center: ("armor.empty"), @@ -158,6 +254,18 @@ offset: (-8.0, -6.0, -9.0), center: ("npc.dullahan.male.torso_lower"), ), + jaw: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-1.5, -9.0, -10.0), center: ("npc.dullahan.male.sword"), @@ -177,6 +285,18 @@ offset: (-8.0, -6.0, -9.0), center: ("npc.dullahan.male.torso_lower"), ), + jaw: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + tail: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), + second: ( + offset: (0.0, 0.0, 0.0), + center: ("armor.empty"), + ), main: ( offset: (-1.5, -9.0, -10.0), center: ("npc.dullahan.male.sword"), diff --git a/voxygen/src/anim/Cargo.toml b/voxygen/src/anim/Cargo.toml index ab4d0e2bfe..d54f1519c9 100644 --- a/voxygen/src/anim/Cargo.toml +++ b/voxygen/src/anim/Cargo.toml @@ -8,7 +8,7 @@ edition = "2018" name = "voxygen_anim" # Uncomment to use animation hot reloading # Note: this breaks `cargo test` -# crate-type = ["lib", "cdylib"] +#crate-type = ["lib", "cdylib"] [features] use-dyn-lib = ["libloading", "notify", "lazy_static", "tracing", "find_folder"] diff --git a/voxygen/src/anim/src/biped_large/idle.rs b/voxygen/src/anim/src/biped_large/idle.rs index d240811ace..8e9ca72cbc 100644 --- a/voxygen/src/anim/src/biped_large/idle.rs +++ b/voxygen/src/anim/src/biped_large/idle.rs @@ -37,6 +37,8 @@ impl Animation for IdleAnimation { * 0.25, ); + let wave_slow = (anim_time as f32 * 0.8).sin(); + next.head.offset = Vec3::new( 0.0, skeleton_attr.head.0, @@ -61,10 +63,27 @@ impl Animation for IdleAnimation { next.lower_torso.ori = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0); next.lower_torso.scale = Vec3::one() * 1.02; + next.jaw.offset = Vec3::new(0.0, skeleton_attr.jaw.0, skeleton_attr.jaw.1); + next.jaw.ori = Quaternion::rotation_x(wave_slow * 0.09); + next.jaw.scale = Vec3::one(); + + next.tail.offset = Vec3::new( + 0.0, + skeleton_attr.tail.0, + skeleton_attr.tail.1 + torso * 0.0, + ); + next.tail.ori = Quaternion::rotation_z(0.0); + next.tail.scale = Vec3::one(); + next.control.offset = Vec3::new(0.0, 0.0, 0.0); next.control.ori = Quaternion::rotation_z(0.0); next.control.scale = Vec3::one(); + next.second.offset = Vec3::new(0.0, 0.0, 0.0); + next.second.ori = + Quaternion::rotation_x(PI) * Quaternion::rotation_y(0.0) * Quaternion::rotation_z(0.0); + next.second.scale = Vec3::one() * 0.0; + next.main.offset = Vec3::new(-5.0, -7.0, 7.0); next.main.ori = Quaternion::rotation_x(PI) * Quaternion::rotation_y(0.6) * Quaternion::rotation_z(1.57); diff --git a/voxygen/src/anim/src/biped_large/jump.rs b/voxygen/src/anim/src/biped_large/jump.rs index 650db18ffb..b2d9c28e90 100644 --- a/voxygen/src/anim/src/biped_large/jump.rs +++ b/voxygen/src/anim/src/biped_large/jump.rs @@ -41,6 +41,14 @@ impl Animation for JumpAnimation { next.lower_torso.ori = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0); next.lower_torso.scale = Vec3::one() * 1.02; + next.jaw.offset = Vec3::new(0.0, skeleton_attr.jaw.0, skeleton_attr.jaw.1); + next.jaw.ori = Quaternion::rotation_z(0.0); + next.jaw.scale = Vec3::one(); + + next.tail.offset = Vec3::new(0.0, skeleton_attr.tail.0, skeleton_attr.tail.1 * 0.0); + next.tail.ori = Quaternion::rotation_z(0.0); + next.tail.scale = Vec3::one(); + next.shoulder_l.offset = Vec3::new( -skeleton_attr.shoulder.0, skeleton_attr.shoulder.1, diff --git a/voxygen/src/anim/src/biped_large/mod.rs b/voxygen/src/anim/src/biped_large/mod.rs index 6af323397f..3f744a3589 100644 --- a/voxygen/src/anim/src/biped_large/mod.rs +++ b/voxygen/src/anim/src/biped_large/mod.rs @@ -15,9 +15,12 @@ use vek::Vec3; #[derive(Clone, Default)] pub struct BipedLargeSkeleton { head: Bone, + jaw: Bone, upper_torso: Bone, lower_torso: Bone, + tail: Bone, main: Bone, + second: Bone, shoulder_l: Bone, shoulder_r: Bone, hand_l: Bone, @@ -40,13 +43,16 @@ impl Skeleton for BipedLargeSkeleton { #[cfg(feature = "use-dyn-lib")] const COMPUTE_FN: &'static [u8] = b"biped_large_compute_mats\0"; - fn bone_count(&self) -> usize { 12 } + fn bone_count(&self) -> usize { 15 } #[cfg_attr(feature = "be-dyn-lib", export_name = "biped_large_compute_mats")] fn compute_matrices_inner(&self) -> ([FigureBoneData; 16], Vec3) { + let jaw_mat = self.jaw.compute_base_matrix(); let upper_torso_mat = self.upper_torso.compute_base_matrix(); let lower_torso_mat = self.lower_torso.compute_base_matrix(); + let tail_mat = self.tail.compute_base_matrix(); let main_mat = self.main.compute_base_matrix(); + let second_mat = self.second.compute_base_matrix(); let shoulder_l_mat = self.shoulder_l.compute_base_matrix(); let shoulder_r_mat = self.shoulder_r.compute_base_matrix(); let hand_l_mat = self.hand_l.compute_base_matrix(); @@ -59,9 +65,14 @@ impl Skeleton for BipedLargeSkeleton { ( [ FigureBoneData::new(torso_mat * upper_torso_mat * self.head.compute_base_matrix()), + FigureBoneData::new( + torso_mat * upper_torso_mat * self.head.compute_base_matrix() * jaw_mat, + ), FigureBoneData::new(torso_mat * upper_torso_mat), FigureBoneData::new(torso_mat * upper_torso_mat * lower_torso_mat), + FigureBoneData::new(torso_mat * upper_torso_mat * lower_torso_mat * tail_mat), FigureBoneData::new(torso_mat * control_mat * upper_torso_mat * main_mat), + FigureBoneData::new(torso_mat * control_mat * upper_torso_mat * second_mat), FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_l_mat), FigureBoneData::new(torso_mat * upper_torso_mat * shoulder_r_mat), FigureBoneData::new(torso_mat * control_mat * upper_torso_mat * hand_l_mat), @@ -71,9 +82,6 @@ impl Skeleton for BipedLargeSkeleton { FigureBoneData::new(self.foot_l.compute_base_matrix()), FigureBoneData::new(self.foot_r.compute_base_matrix()), FigureBoneData::default(), - FigureBoneData::default(), - FigureBoneData::default(), - FigureBoneData::default(), ], Vec3::default(), ) @@ -81,9 +89,12 @@ impl Skeleton for BipedLargeSkeleton { fn interpolate(&mut self, target: &Self, dt: f32) { self.head.interpolate(&target.head, dt); + self.jaw.interpolate(&target.jaw, dt); self.upper_torso.interpolate(&target.upper_torso, dt); self.lower_torso.interpolate(&target.lower_torso, dt); + self.tail.interpolate(&target.tail, dt); self.main.interpolate(&target.main, dt); + self.second.interpolate(&target.second, dt); self.shoulder_l.interpolate(&target.shoulder_l, dt); self.shoulder_r.interpolate(&target.shoulder_r, dt); self.hand_l.interpolate(&target.hand_l, dt); @@ -99,8 +110,10 @@ impl Skeleton for BipedLargeSkeleton { pub struct SkeletonAttr { head: (f32, f32), + jaw: (f32, f32), upper_torso: (f32, f32), lower_torso: (f32, f32), + tail: (f32, f32), shoulder: (f32, f32, f32), hand: (f32, f32, f32), leg: (f32, f32, f32), @@ -122,8 +135,10 @@ impl Default for SkeletonAttr { fn default() -> Self { Self { head: (0.0, 0.0), + jaw: (0.0, 0.0), upper_torso: (0.0, 0.0), lower_torso: (0.0, 0.0), + tail: (0.0, 0.0), shoulder: (0.0, 0.0, 0.0), hand: (0.0, 0.0, 0.0), leg: (0.0, 0.0, 0.0), @@ -143,6 +158,13 @@ impl<'a> From<&'a comp::biped_large::Body> for SkeletonAttr { (Troll, _) => (6.0, 10.0), (Dullahan, _) => (3.0, 6.0), }, + jaw: match (body.species, body.body_type) { + (Ogre, _) => (0.0, 0.0), + (Cyclops, _) => (0.0, 0.0), + (Wendigo, _) => (0.0, 0.0), + (Troll, _) => (2.0, -4.0), + (Dullahan, _) => (0.0, 0.0), + }, upper_torso: match (body.species, body.body_type) { (Ogre, _) => (0.0, 19.0), (Cyclops, _) => (-2.0, 27.0), @@ -157,11 +179,18 @@ impl<'a> From<&'a comp::biped_large::Body> for SkeletonAttr { (Troll, _) => (1.0, -10.5), (Dullahan, _) => (0.0, -6.5), }, + tail: match (body.species, body.body_type) { + (Ogre, _) => (0.0, 0.0), + (Cyclops, _) => (0.0, 0.0), + (Wendigo, _) => (0.0, 0.0), + (Troll, _) => (0.0, 0.0), + (Dullahan, _) => (0.0, 0.0), + }, shoulder: match (body.species, body.body_type) { (Ogre, _) => (6.1, 0.5, 2.5), (Cyclops, _) => (9.5, 2.5, 2.5), (Wendigo, _) => (9.0, 0.5, -0.5), - (Troll, _) => (11.0, 0.5, -2.5), + (Troll, _) => (11.0, 0.5, -1.5), (Dullahan, _) => (14.0, 0.5, 4.5), }, hand: match (body.species, body.body_type) { diff --git a/voxygen/src/anim/src/biped_large/run.rs b/voxygen/src/anim/src/biped_large/run.rs index ac33aa2fb9..a7929510f9 100644 --- a/voxygen/src/anim/src/biped_large/run.rs +++ b/voxygen/src/anim/src/biped_large/run.rs @@ -77,6 +77,19 @@ impl Animation for RunAnimation { next.lower_torso.ori = Quaternion::rotation_z(short * 0.15) * Quaternion::rotation_x(0.14); next.lower_torso.scale = Vec3::one() * 1.02; + next.jaw.offset = Vec3::new(0.0, skeleton_attr.jaw.0, skeleton_attr.jaw.1); + next.jaw.ori = Quaternion::rotation_z(0.0); + next.jaw.scale = Vec3::one(); + + next.tail.offset = Vec3::new(0.0, skeleton_attr.tail.0, skeleton_attr.tail.1 * 0.0); + next.tail.ori = Quaternion::rotation_z(0.0); + next.tail.scale = Vec3::one(); + + next.second.offset = Vec3::new(0.0, 0.0, 0.0); + next.second.ori = + Quaternion::rotation_x(PI) * Quaternion::rotation_y(0.0) * Quaternion::rotation_z(0.0); + next.second.scale = Vec3::one() * 0.0; + next.control.offset = Vec3::new(0.0, 0.0, 0.0); next.control.ori = Quaternion::rotation_z(0.0); next.control.scale = Vec3::one(); diff --git a/voxygen/src/anim/src/biped_large/wield.rs b/voxygen/src/anim/src/biped_large/wield.rs index 4edd995536..9ab73c16eb 100644 --- a/voxygen/src/anim/src/biped_large/wield.rs +++ b/voxygen/src/anim/src/biped_large/wield.rs @@ -77,6 +77,11 @@ impl Animation for WieldAnimation { * Quaternion::rotation_z(1.0); next.main.scale = Vec3::one() * 1.02; + next.second.offset = Vec3::new(0.0, 0.0, 0.0); + next.second.ori = + Quaternion::rotation_x(PI) * Quaternion::rotation_y(0.0) * Quaternion::rotation_z(0.0); + next.second.scale = Vec3::one() * 0.0; + next.hand_l.offset = Vec3::new( -skeleton_attr.hand.0 - 7.0, skeleton_attr.hand.1 - 7.0, @@ -119,6 +124,14 @@ impl Animation for WieldAnimation { next.lower_torso.ori = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0); next.lower_torso.scale = Vec3::one() * 1.02; + next.jaw.offset = Vec3::new(0.0, skeleton_attr.jaw.0, skeleton_attr.jaw.1 * 0.0); + next.jaw.ori = Quaternion::rotation_z(0.0); + next.jaw.scale = Vec3::one(); + + next.tail.offset = Vec3::new(0.0, skeleton_attr.tail.0, skeleton_attr.tail.1); + next.tail.ori = Quaternion::rotation_z(0.0); + next.tail.scale = Vec3::one(); + next.shoulder_l.offset = Vec3::new( -skeleton_attr.shoulder.0, skeleton_attr.shoulder.1, diff --git a/voxygen/src/anim/src/character/swim.rs b/voxygen/src/anim/src/character/swim.rs index e7e23023ae..3d28c3bdff 100644 --- a/voxygen/src/anim/src/character/swim.rs +++ b/voxygen/src/anim/src/character/swim.rs @@ -88,15 +88,12 @@ impl Animation for SwimAnimation { next.chest.scale = Vec3::one(); next.belt.offset = Vec3::new(0.0, skeleton_attr.belt.0, skeleton_attr.belt.1); - next.belt.ori = Quaternion::rotation_z(short * 0.30); next.belt.scale = Vec3::one(); next.back.offset = Vec3::new(0.0, skeleton_attr.back.0, skeleton_attr.back.1); - next.back.ori = Quaternion::rotation_z(0.0); next.back.scale = Vec3::one() * 1.02; next.shorts.offset = Vec3::new(0.0, skeleton_attr.shorts.0, skeleton_attr.shorts.1); - next.shorts.ori = Quaternion::rotation_z(short * 0.5); next.shorts.scale = Vec3::one(); next.l_hand.offset = Vec3::new( diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index 5aadd9efac..98ee3824e3 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -576,6 +576,11 @@ impl FigureModelCache { body.body_type, generate_mesh, )), + Some(biped_large_center_spec.mesh_jaw( + body.species, + body.body_type, + generate_mesh, + )), Some(biped_large_center_spec.mesh_torso_upper( body.species, body.body_type, @@ -586,11 +591,21 @@ impl FigureModelCache { body.body_type, generate_mesh, )), + Some(biped_large_center_spec.mesh_tail( + body.species, + body.body_type, + generate_mesh, + )), Some(biped_large_center_spec.mesh_main( body.species, body.body_type, generate_mesh, )), + Some(biped_large_center_spec.mesh_second( + body.species, + body.body_type, + generate_mesh, + )), Some(biped_large_lateral_spec.mesh_shoulder_l( body.species, body.body_type, @@ -632,9 +647,6 @@ impl FigureModelCache { generate_mesh, )), None, - None, - None, - None, ] }, Body::Golem(body) => { diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index 007a4c91ee..aafa1b8970 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -2481,9 +2481,12 @@ pub struct BipedLargeCenterSpec(HashMap<(BLSpecies, BLBodyType), SidedBLCenterVo #[derive(Serialize, Deserialize)] struct SidedBLCenterVoxSpec { head: BipedLargeCenterSubSpec, + jaw: BipedLargeCenterSubSpec, torso_upper: BipedLargeCenterSubSpec, torso_lower: BipedLargeCenterSubSpec, + tail: BipedLargeCenterSubSpec, main: BipedLargeCenterSubSpec, + second: BipedLargeCenterSubSpec, } #[derive(Serialize, Deserialize)] struct BipedLargeCenterSubSpec { @@ -2554,6 +2557,27 @@ impl BipedLargeCenterSpec { generate_mesh(¢er, Vec3::from(spec.head.offset)) } + pub fn mesh_jaw( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No jaw specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); + }, + }; + let center = graceful_load_segment(&spec.jaw.center.0); + + generate_mesh(¢er, Vec3::from(spec.jaw.offset)) + } + pub fn mesh_torso_upper( &self, species: BLSpecies, @@ -2596,6 +2620,27 @@ impl BipedLargeCenterSpec { generate_mesh(¢er, Vec3::from(spec.torso_lower.offset)) } + pub fn mesh_tail( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No tail specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); + }, + }; + let center = graceful_load_segment(&spec.tail.center.0); + + generate_mesh(¢er, Vec3::from(spec.tail.offset)) + } + pub fn mesh_main( &self, species: BLSpecies, @@ -2616,6 +2661,27 @@ impl BipedLargeCenterSpec { generate_mesh(¢er, Vec3::from(spec.main.offset)) } + + pub fn mesh_second( + &self, + species: BLSpecies, + body_type: BLBodyType, + generate_mesh: impl FnOnce(&Segment, Vec3) -> Mesh, + ) -> Mesh { + let spec = match self.0.get(&(species, body_type)) { + Some(spec) => spec, + None => { + error!( + "No second weapon specification exists for the combination of {:?} and {:?}", + species, body_type + ); + return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5), generate_mesh); + }, + }; + let center = graceful_load_segment(&spec.second.center.0); + + generate_mesh(¢er, Vec3::from(spec.second.offset)) + } } impl BipedLargeLateralSpec { pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc {