From 54bad4b20503845c0f65a5b89c36cca31f4ff0ec Mon Sep 17 00:00:00 2001 From: IsseW Date: Wed, 2 Nov 2022 03:00:40 +0100 Subject: [PATCH] Creature viewpoint --- voxygen/anim/src/arthropod/mod.rs | 1 + voxygen/anim/src/biped_large/mod.rs | 5 +- voxygen/anim/src/biped_small/mod.rs | 4 +- voxygen/anim/src/bird_large/mod.rs | 1 + voxygen/anim/src/bird_medium/mod.rs | 8 +- voxygen/anim/src/character/mod.rs | 1 + voxygen/anim/src/dragon/mod.rs | 1 + voxygen/anim/src/fish_medium/mod.rs | 7 +- voxygen/anim/src/fish_small/mod.rs | 1 + voxygen/anim/src/fixture/mod.rs | 1 + voxygen/anim/src/golem/mod.rs | 4 +- voxygen/anim/src/item_drop/mod.rs | 1 + voxygen/anim/src/lib.rs | 1 + voxygen/anim/src/object/mod.rs | 1 + voxygen/anim/src/quadruped_low/mod.rs | 1 + voxygen/anim/src/quadruped_medium/mod.rs | 24 ++ voxygen/anim/src/quadruped_small/mod.rs | 1 + voxygen/anim/src/ship/mod.rs | 1 + voxygen/anim/src/theropod/mod.rs | 1 + voxygen/src/scene/figure/load.rs | 298 ++++++++++++++--------- voxygen/src/scene/figure/mod.rs | 100 ++++++++ voxygen/src/scene/figure/volume.rs | 1 + voxygen/src/scene/mod.rs | 88 ++++--- 23 files changed, 393 insertions(+), 159 deletions(-) diff --git a/voxygen/anim/src/arthropod/mod.rs b/voxygen/anim/src/arthropod/mod.rs index c9aee5f244..3e34dbaa65 100644 --- a/voxygen/anim/src/arthropod/mod.rs +++ b/voxygen/anim/src/arthropod/mod.rs @@ -108,6 +108,7 @@ impl Skeleton for ArthropodSkeleton { Offsets { lantern: None, + viewpoint: Some((head_mat * Vec4::new(0.0, 7.0, 0.0, 1.0)).xyz()), mount_bone: Transform { position: mount_position, orientation: mount_orientation, diff --git a/voxygen/anim/src/biped_large/mod.rs b/voxygen/anim/src/biped_large/mod.rs index c18cdc39ef..baba6bd0f5 100644 --- a/voxygen/anim/src/biped_large/mod.rs +++ b/voxygen/anim/src/biped_large/mod.rs @@ -104,9 +104,11 @@ impl Skeleton for BipedLargeSkeleton { let head_mat = upper_torso_mat * Mat4::::from(self.head); let hand_l_mat = Mat4::::from(self.hand_l); + let jaw_mat = head_mat * Mat4::::from(self.jaw); + *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [ make_bone(head_mat), - make_bone(head_mat * Mat4::::from(self.jaw)), + make_bone(jaw_mat), make_bone(upper_torso_mat), make_bone(lower_torso_mat), make_bone(lower_torso_mat * Mat4::::from(self.tail)), @@ -129,6 +131,7 @@ impl Skeleton for BipedLargeSkeleton { ]; Offsets { lantern: None, + viewpoint: Some((jaw_mat * Vec4::new(0.0, 4.0, 0.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::BipedLarge(body) diff --git a/voxygen/anim/src/biped_small/mod.rs b/voxygen/anim/src/biped_small/mod.rs index e1bacfaa63..9348e597b1 100644 --- a/voxygen/anim/src/biped_small/mod.rs +++ b/voxygen/anim/src/biped_small/mod.rs @@ -62,8 +62,9 @@ impl Skeleton for BipedSmallSkeleton { let control_mat = chest_mat * Mat4::::from(self.control); let control_l_mat = Mat4::::from(self.control_l); let control_r_mat = Mat4::::from(self.control_r); + let head_mat = chest_mat * Mat4::::from(self.head); *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [ - make_bone(chest_mat * Mat4::::from(self.head)), + make_bone(head_mat), make_bone(chest_mat), make_bone(pants_mat), make_bone(pants_mat * Mat4::::from(self.tail)), @@ -75,6 +76,7 @@ impl Skeleton for BipedSmallSkeleton { ]; Offsets { lantern: None, + viewpoint: Some((head_mat * Vec4::new(0.0, 0.0, 0.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::BipedSmall(body) diff --git a/voxygen/anim/src/bird_large/mod.rs b/voxygen/anim/src/bird_large/mod.rs index 9b978e610d..252fc41612 100644 --- a/voxygen/anim/src/bird_large/mod.rs +++ b/voxygen/anim/src/bird_large/mod.rs @@ -98,6 +98,7 @@ impl Skeleton for BirdLargeSkeleton { ]; Offsets { lantern: None, + viewpoint: Some((head_mat * Vec4::new(0.0, 3.0, 6.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::BirdLarge(body) diff --git a/voxygen/anim/src/bird_medium/mod.rs b/voxygen/anim/src/bird_medium/mod.rs index ae40a59de2..80a4f40cf4 100644 --- a/voxygen/anim/src/bird_medium/mod.rs +++ b/voxygen/anim/src/bird_medium/mod.rs @@ -40,9 +40,10 @@ impl Skeleton for BirdMediumSkeleton { ) -> Offsets { let base_mat = base_mat * Mat4::scaling_3d(1.0 / 11.0); let torso_mat = base_mat * Mat4::::from(self.torso); + let head_mat = torso_mat * Mat4::::from(self.head); *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [ - make_bone(torso_mat * Mat4::::from(self.head)), + make_bone(head_mat), make_bone(torso_mat), make_bone(torso_mat * Mat4::::from(self.tail)), make_bone(torso_mat * Mat4::::from(self.wing_l)), @@ -50,8 +51,13 @@ impl Skeleton for BirdMediumSkeleton { make_bone(base_mat * Mat4::::from(self.leg_l)), make_bone(base_mat * Mat4::::from(self.leg_r)), ]; + use common::comp::body::bird_medium::Species::*; Offsets { lantern: None, + viewpoint: match body.species { + Bat => Some((head_mat * Vec4::new(0.0, 5.0, -4.0, 1.0)).xyz()), + _ => Some((head_mat * Vec4::new(0.0, 3.0, 2.0, 1.0)).xyz()), + }, // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::BirdMedium(body) diff --git a/voxygen/anim/src/character/mod.rs b/voxygen/anim/src/character/mod.rs index be145c6639..ba20f2d4b2 100644 --- a/voxygen/anim/src/character/mod.rs +++ b/voxygen/anim/src/character/mod.rs @@ -165,6 +165,7 @@ impl Skeleton for CharacterSkeleton { let weapon_trails = self.main_weapon_trail || self.off_weapon_trail; Offsets { lantern: Some((lantern_mat * Vec4::new(0.0, 0.5, -6.0, 1.0)).xyz()), + viewpoint: Some((head_mat * Vec4::new(0.0, 0.0, 4.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::Humanoid(body) diff --git a/voxygen/anim/src/dragon/mod.rs b/voxygen/anim/src/dragon/mod.rs index 62315faf77..2368fafd5a 100644 --- a/voxygen/anim/src/dragon/mod.rs +++ b/voxygen/anim/src/dragon/mod.rs @@ -73,6 +73,7 @@ impl Skeleton for DragonSkeleton { ]; Offsets { lantern: None, + viewpoint: Some((head_upper_mat * Vec4::new(0.0, 8.0, 0.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::Dragon(body).mount_offset().into_tuple().into(), diff --git a/voxygen/anim/src/fish_medium/mod.rs b/voxygen/anim/src/fish_medium/mod.rs index 8cfa71d130..7414f5abce 100644 --- a/voxygen/anim/src/fish_medium/mod.rs +++ b/voxygen/anim/src/fish_medium/mod.rs @@ -39,11 +39,11 @@ impl Skeleton for FishMediumSkeleton { let chest_front_mat = base_mat * Mat4::::from(self.chest_front); let chest_back_mat = Mat4::::from(self.chest_back); - let head_mat = Mat4::::from(self.head); + let head_mat = chest_front_mat * Mat4::::from(self.head); *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [ - make_bone(chest_front_mat * head_mat), - make_bone(chest_front_mat * head_mat * Mat4::::from(self.jaw)), + make_bone(head_mat), + make_bone(head_mat * Mat4::::from(self.jaw)), make_bone(chest_front_mat), make_bone(chest_front_mat * chest_back_mat), make_bone(chest_front_mat * chest_back_mat * Mat4::::from(self.tail)), @@ -52,6 +52,7 @@ impl Skeleton for FishMediumSkeleton { ]; Offsets { lantern: None, + viewpoint: Some((head_mat * Vec4::new(0.0, 5.0, 0.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::FishMedium(body) diff --git a/voxygen/anim/src/fish_small/mod.rs b/voxygen/anim/src/fish_small/mod.rs index 4086be7115..3fcd9a68e8 100644 --- a/voxygen/anim/src/fish_small/mod.rs +++ b/voxygen/anim/src/fish_small/mod.rs @@ -43,6 +43,7 @@ impl Skeleton for FishSmallSkeleton { ]; Offsets { lantern: None, + viewpoint: Some((chest_mat * Vec4::new(0.0, 3.0, 0.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::FishSmall(body) diff --git a/voxygen/anim/src/fixture/mod.rs b/voxygen/anim/src/fixture/mod.rs index 31f7d59d68..c39ff99d05 100644 --- a/voxygen/anim/src/fixture/mod.rs +++ b/voxygen/anim/src/fixture/mod.rs @@ -36,6 +36,7 @@ impl Skeleton for FixtureSkeleton { buf[0] = make_bone(base_mat); Offsets { lantern: None, + viewpoint: None, mount_bone: Transform::default(), primary_trail_mat: None, secondary_trail_mat: None, diff --git a/voxygen/anim/src/golem/mod.rs b/voxygen/anim/src/golem/mod.rs index cab3f0b853..6539c2fb27 100644 --- a/voxygen/anim/src/golem/mod.rs +++ b/voxygen/anim/src/golem/mod.rs @@ -58,9 +58,10 @@ impl Skeleton for GolemSkeleton { let leg_r_mat = lower_torso_mat * Mat4::::from(self.leg_r); let shoulder_l_mat = upper_torso_mat * Mat4::::from(self.shoulder_l); let shoulder_r_mat = upper_torso_mat * Mat4::::from(self.shoulder_r); + let head_mat = upper_torso_mat * Mat4::::from(self.head); *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [ - make_bone(upper_torso_mat * Mat4::::from(self.head)), + make_bone(head_mat), make_bone(upper_torso_mat * Mat4::::from(self.head) * Mat4::::from(self.jaw)), make_bone(upper_torso_mat), make_bone(lower_torso_mat), @@ -75,6 +76,7 @@ impl Skeleton for GolemSkeleton { ]; Offsets { lantern: None, + viewpoint: Some((head_mat * Vec4::new(0.0, 0.0, 5.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::Golem(body).mount_offset().into_tuple().into(), diff --git a/voxygen/anim/src/item_drop/mod.rs b/voxygen/anim/src/item_drop/mod.rs index ac7e9322fd..beb139c150 100644 --- a/voxygen/anim/src/item_drop/mod.rs +++ b/voxygen/anim/src/item_drop/mod.rs @@ -36,6 +36,7 @@ impl Skeleton for ItemDropSkeleton { [make_bone(bone0_mat)]; Offsets { lantern: None, + viewpoint: None, mount_bone: Transform { position: comp::Body::ItemDrop(body) .mount_offset() diff --git a/voxygen/anim/src/lib.rs b/voxygen/anim/src/lib.rs index a0234f1ab1..d1ea5a54ae 100644 --- a/voxygen/anim/src/lib.rs +++ b/voxygen/anim/src/lib.rs @@ -107,6 +107,7 @@ pub fn init() { lazy_static::initialize(&LIB); } // Offsets that will be returned after computing the skeleton matrices pub struct Offsets { pub lantern: Option>, + pub viewpoint: Option>, pub mount_bone: Transform, pub primary_trail_mat: Option<(Mat4, TrailSource)>, pub secondary_trail_mat: Option<(Mat4, TrailSource)>, diff --git a/voxygen/anim/src/object/mod.rs b/voxygen/anim/src/object/mod.rs index 7867ac7515..034d6002e4 100644 --- a/voxygen/anim/src/object/mod.rs +++ b/voxygen/anim/src/object/mod.rs @@ -41,6 +41,7 @@ impl Skeleton for ObjectSkeleton { ]; Offsets { lantern: None, + viewpoint: None, // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::Object(body).mount_offset().into_tuple().into(), diff --git a/voxygen/anim/src/quadruped_low/mod.rs b/voxygen/anim/src/quadruped_low/mod.rs index 7e13941213..a885d0ce98 100644 --- a/voxygen/anim/src/quadruped_low/mod.rs +++ b/voxygen/anim/src/quadruped_low/mod.rs @@ -95,6 +95,7 @@ impl Skeleton for QuadrupedLowSkeleton { Offsets { lantern: None, + viewpoint: Some((head_upper_mat * Vec4::new(0.0, 4.0, 1.0, 1.0)).xyz()), mount_bone: Transform { position: mount_position, orientation: mount_orientation, diff --git a/voxygen/anim/src/quadruped_medium/mod.rs b/voxygen/anim/src/quadruped_medium/mod.rs index 1897e9eef6..03550d463c 100644 --- a/voxygen/anim/src/quadruped_medium/mod.rs +++ b/voxygen/anim/src/quadruped_medium/mod.rs @@ -105,6 +105,30 @@ impl Skeleton for QuadrupedMediumSkeleton { Offsets { lantern: None, + viewpoint: match body.species { + Akhlut | Catoblepas | Lion => { + Some((head_mat * Vec4::new(0.0, 8.0, 0.0, 1.0)).xyz()) + }, + Barghest | Saber => Some((head_mat * Vec4::new(0.0, 8.0, 3.0, 1.0)).xyz()), + Cattle | Highland | Bonerattler | Ngoubou | Yak => { + Some((head_mat * Vec4::new(0.0, 6.0, -1.0, 1.0)).xyz()) + }, + Antelope | Deer | Donkey | Bear | Mouflon | Panda => { + Some((head_mat * Vec4::new(0.0, 3.0, 3.0, 1.0)).xyz()) + }, + Camel | Hirdrasil | Horse | Kelpie | Zebra => { + Some((head_mat * Vec4::new(0.0, 2.0, 5.0, 1.0)).xyz()) + }, + Darkhound | Llama | Snowleopard | Tiger | Wolf => { + Some((head_mat * Vec4::new(0.0, 4.0, 1.0, 1.0)).xyz()) + }, + Dreadhorn | Mammoth | Moose | Tarasque => { + Some((head_mat * Vec4::new(0.0, 13.0, -3.0, 1.0)).xyz()) + }, + Frostfang => Some((head_mat * Vec4::new(0.0, 5.0, 3.0, 1.0)).xyz()), + Grolgar | Roshwalr => Some((head_mat * Vec4::new(0.0, 8.0, 6.0, 1.0)).xyz()), + _ => Some((head_mat * Vec4::new(0.0, 2.0, 0.0, 1.0)).xyz()), + }, mount_bone: Transform { position: mount_position, orientation: mount_orientation, diff --git a/voxygen/anim/src/quadruped_small/mod.rs b/voxygen/anim/src/quadruped_small/mod.rs index 2303e88169..475454210c 100644 --- a/voxygen/anim/src/quadruped_small/mod.rs +++ b/voxygen/anim/src/quadruped_small/mod.rs @@ -65,6 +65,7 @@ impl Skeleton for QuadrupedSmallSkeleton { Offsets { lantern: None, + viewpoint: Some((head_mat * Vec4::new(0.0, 3.0, 0.0, 1.0)).xyz()), mount_bone: Transform { position: mount_position, orientation: mount_orientation, diff --git a/voxygen/anim/src/ship/mod.rs b/voxygen/anim/src/ship/mod.rs index ef41bdd4d4..81c9b33f2c 100644 --- a/voxygen/anim/src/ship/mod.rs +++ b/voxygen/anim/src/ship/mod.rs @@ -43,6 +43,7 @@ impl Skeleton for ShipSkeleton { ]; Offsets { lantern: None, + viewpoint: None, // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: (base_mat * scale_mat) diff --git a/voxygen/anim/src/theropod/mod.rs b/voxygen/anim/src/theropod/mod.rs index ef0d8ffccb..f8f96337b4 100644 --- a/voxygen/anim/src/theropod/mod.rs +++ b/voxygen/anim/src/theropod/mod.rs @@ -76,6 +76,7 @@ impl Skeleton for TheropodSkeleton { ]; Offsets { lantern: None, + viewpoint: Some((head_mat * Vec4::new(0.0, 2.0, 0.0, 1.0)).xyz()), // TODO: see quadruped_medium for how to animate this mount_bone: Transform { position: comp::Body::Theropod(body) diff --git a/voxygen/src/scene/figure/load.rs b/voxygen/src/scene/figure/load.rs index e1df730976..d9d7a9c623 100644 --- a/voxygen/src/scene/figure/load.rs +++ b/voxygen/src/scene/figure/load.rs @@ -1078,12 +1078,16 @@ make_vox_spec!( central: QuadrupedSmallCentralSpec = "voxygen.voxel.quadruped_small_central_manifest", lateral: QuadrupedSmallLateralSpec = "voxygen.voxel.quadruped_small_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_chest( body.species, body.body_type, @@ -1282,20 +1286,28 @@ make_vox_spec!( central: QuadrupedMediumCentralSpec = "voxygen.voxel.quadruped_medium_central_manifest", lateral: QuadrupedMediumLateralSpec = "voxygen.voxel.quadruped_medium_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head( - body.species, - body.body_type, - )), - Some(spec.central.read().0.mesh_neck( - body.species, - body.body_type, - )), - Some(spec.central.read().0.mesh_jaw( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.central.read().0.mesh_neck( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.central.read().0.mesh_jaw( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_tail( body.species, body.body_type, @@ -1308,10 +1320,12 @@ make_vox_spec!( body.species, body.body_type, )), - Some(spec.central.read().0.mesh_ears( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_ears( + body.species, + body.body_type, + ) + }), Some(spec.lateral.read().0.mesh_leg_fl( body.species, body.body_type, @@ -1631,12 +1645,16 @@ make_vox_spec!( central: BirdMediumCentralSpec = "voxygen.voxel.bird_medium_central_manifest", lateral: BirdMediumLateralSpec = "voxygen.voxel.bird_medium_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_torso( body.species, body.body_type, @@ -1830,16 +1848,22 @@ make_vox_spec!( central: TheropodCentralSpec = "voxygen.voxel.theropod_central_manifest", lateral: TheropodLateralSpec = "voxygen.voxel.theropod_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head( - body.species, - body.body_type, - )), - Some(spec.central.read().0.mesh_jaw( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.central.read().0.mesh_jaw( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_neck( body.species, body.body_type, @@ -2147,24 +2171,32 @@ make_vox_spec!( central: ArthropodCentralSpec = "voxygen.voxel.arthropod_central_manifest", lateral: ArthropodLateralSpec = "voxygen.voxel.arthropod_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_chest( body.species, body.body_type, )), - Some(spec.lateral.read().0.mesh_mandible_l( - body.species, - body.body_type, - )), - Some(spec.lateral.read().0.mesh_mandible_r( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.lateral.read().0.mesh_mandible_l( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.lateral.read().0.mesh_mandible_r( + body.species, + body.body_type, + ) + }), Some(spec.lateral.read().0.mesh_wing_fl( body.species, body.body_type, @@ -2515,12 +2547,16 @@ make_vox_spec!( central: FishMediumCentralSpec = "voxygen.voxel.fish_medium_central_manifest", lateral: FishMediumLateralSpec = "voxygen.voxel.fish_medium_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_jaw( body.species, body.body_type, @@ -2707,12 +2743,16 @@ make_vox_spec!( central: FishSmallCentralSpec = "voxygen.voxel.fish_small_central_manifest", lateral: FishSmallLateralSpec = "voxygen.voxel.fish_small_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_chest( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_chest( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_tail( body.species, body.body_type, @@ -2856,7 +2896,7 @@ make_vox_spec!( let foot = loadout.foot.as_deref(); -[ + [ third_person.map(|loadout| { spec.armor_head.read().0.mesh_head( loadout.head.as_deref(), @@ -3131,20 +3171,26 @@ make_vox_spec!( central: DragonCentralSpec = "voxygen.voxel.dragon_central_manifest", lateral: DragonLateralSpec = "voxygen.voxel.dragon_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head_upper( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head_upper( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_head_lower( body.species, body.body_type, )), - Some(spec.central.read().0.mesh_jaw( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_jaw( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_chest_front( body.species, body.body_type, @@ -3488,16 +3534,22 @@ make_vox_spec!( central: BirdLargeCentralSpec = "voxygen.voxel.bird_large_central_manifest", lateral: BirdLargeLateralSpec = "voxygen.voxel.bird_large_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head( - body.species, - body.body_type, - )), - Some(spec.central.read().0.mesh_beak( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.central.read().0.mesh_beak( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_neck( body.species, body.body_type, @@ -3879,21 +3931,29 @@ make_vox_spec!( // TODO: This is bad code, maybe this method should return Option<_> let loadout = extra.as_deref().unwrap_or(&DEFAULT_LOADOUT); + let third_person = loadout.third_person.as_ref(); + //let third_person = loadout.third_person.as_ref(); let tool = loadout.tool.as_ref(); [ - Some(spec.central.read().0.mesh_head( - body.species, - body.body_type, - )), - Some(spec.central.read().0.mesh_jaw( - body.species, - body.body_type, - )), - Some(spec.central.read().0.mesh_torso_upper( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.central.read().0.mesh_jaw( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.central.read().0.mesh_torso_upper( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_torso_lower( body.species, body.body_type, @@ -4262,16 +4322,22 @@ make_vox_spec!( central: GolemCentralSpec = "voxygen.voxel.golem_central_manifest", lateral: GolemLateralSpec = "voxygen.voxel.golem_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head( - body.species, - body.body_type, - )), - Some(spec.central.read().0.mesh_jaw( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.central.read().0.mesh_jaw( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_torso_upper( body.species, body.body_type, @@ -4556,20 +4622,28 @@ make_vox_spec!( central: QuadrupedLowCentralSpec = "voxygen.voxel.quadruped_low_central_manifest", lateral: QuadrupedLowLateralSpec = "voxygen.voxel.quadruped_low_lateral_manifest", }, - |FigureKey { body, .. }, spec| { + |FigureKey { body, extra, .. }, spec| { + let third_person = extra.as_ref().and_then(|loadout| loadout.third_person.as_ref()); + [ - Some(spec.central.read().0.mesh_head_upper( - body.species, - body.body_type, - )), - Some(spec.central.read().0.mesh_head_lower( - body.species, - body.body_type, - )), - Some(spec.central.read().0.mesh_jaw( - body.species, - body.body_type, - )), + third_person.map(|_| { + spec.central.read().0.mesh_head_upper( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.central.read().0.mesh_head_lower( + body.species, + body.body_type, + ) + }), + third_person.map(|_| { + spec.central.read().0.mesh_jaw( + body.species, + body.body_type, + ) + }), Some(spec.central.read().0.mesh_chest( body.species, body.body_type, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 7b3980223c..e19b1be1a6 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -6517,6 +6517,103 @@ impl FigureMgr { } } + pub fn viewpoint_offset(&self, scene_data: &SceneData, entity: EcsEntity) -> Vec3 { + scene_data + .state + .ecs() + .read_storage::() + .get(entity) + .and_then(|b| match b { + Body::Humanoid(_) => self + .states + .character_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::QuadrupedSmall(_) => self + .states + .quadruped_small_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::QuadrupedMedium(_) => self + .states + .quadruped_medium_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::BirdMedium(_) => self + .states + .bird_medium_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::FishMedium(_) => self + .states + .fish_medium_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::Dragon(_) => self + .states + .dragon_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::BirdLarge(_) => self + .states + .bird_large_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::FishSmall(_) => self + .states + .fish_small_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::BipedLarge(_) => self + .states + .biped_large_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::BipedSmall(_) => self + .states + .biped_small_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::Golem(_) => self + .states + .golem_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::Theropod(_) => self + .states + .theropod_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::QuadrupedLow(_) => self + .states + .quadruped_low_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::Arthropod(_) => self + .states + .arthropod_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::Object(_) => self + .states + .object_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::Ship(_) => self + .states + .ship_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + Body::ItemDrop(_) => self + .states + .item_drop_states + .get(&entity) + .and_then(|state| state.viewpoint_offset), + }) + .map(|viewpoint| viewpoint.into()) + .unwrap_or_else(Vec3::zero) + } + pub fn figure_count(&self) -> usize { self.states.count() } pub fn figure_count_visible(&self) -> usize { self.states.count_visible() } @@ -6625,6 +6722,7 @@ impl FigureColLights { pub struct FigureStateMeta { lantern_offset: Option>, + viewpoint_offset: Option>, main_abs_trail_points: Option<(anim::vek::Vec3, anim::vek::Vec3)>, off_abs_trail_points: Option<(anim::vek::Vec3, anim::vek::Vec3)>, // Animation to be applied to rider of this entity @@ -6710,6 +6808,7 @@ impl FigureState { Self { meta: FigureStateMeta { lantern_offset: offsets.lantern, + viewpoint_offset: offsets.viewpoint, main_abs_trail_points: None, off_abs_trail_points: None, mount_transform: offsets.mount_bone, @@ -6890,6 +6989,7 @@ impl FigureState { renderer.update_consts(&mut self.meta.bound.1, &new_bone_consts[0..S::BONE_COUNT]); self.lantern_offset = offsets.lantern; + self.viewpoint_offset = offsets.viewpoint; // Handle weapon trails fn handle_weapon_trails( trail_mgr: &mut TrailMgr, diff --git a/voxygen/src/scene/figure/volume.rs b/voxygen/src/scene/figure/volume.rs index d2518a98b6..813592ebb6 100644 --- a/voxygen/src/scene/figure/volume.rs +++ b/voxygen/src/scene/figure/volume.rs @@ -59,6 +59,7 @@ impl anim::Skeleton for VolumeKey { anim::Offsets { lantern: None, + viewpoint: None, mount_bone: anim::vek::Transform::default(), primary_trail_mat: None, secondary_trail_mat: None, diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 910970ca8a..56a55be686 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -524,28 +524,16 @@ impl Scene { .get(scene_data.viewpoint_entity) .map_or(Quaternion::identity(), |ori| ori.to_quat()); - let viewpoint_rolling = ecs - .read_storage::() - .get(scene_data.viewpoint_entity) - .map_or(false, |cs| cs.is_dodge()); - - let is_running = ecs - .read_storage::() - .get(scene_data.viewpoint_entity) - .map(|v| v.0.magnitude_squared() > RUNNING_THRESHOLD.powi(2)) - .unwrap_or(false); - - let on_ground = ecs - .read_storage::() - .get(scene_data.viewpoint_entity) - .map(|p| p.on_ground.is_some()); - - let (viewpoint_height, viewpoint_eye_height) = scene_data - .state - .ecs() + let (is_humanoid, viewpoint_height, viewpoint_eye_height) = ecs .read_storage::() .get(scene_data.viewpoint_entity) - .map_or((1.0, 0.0), |b| (b.height(), b.eye_height())); + .map_or((false, 1.0, 0.0), |b| { + ( + matches!(b, comp::Body::Humanoid(_)), + b.height(), + b.eye_height(), + ) + }); if scene_data.mutable_viewpoint || matches!(self.camera.get_mode(), CameraMode::Freefly) { @@ -576,31 +564,51 @@ impl Scene { .set_orientation_instant(Vec3::new(-yaw, pitch, roll)); } - // Alter camera position to match player. - let tilt = self.camera.get_orientation().y; - let dist = self.camera.get_distance(); + let viewpoint_offset = if is_humanoid { + let viewpoint_rolling = ecs + .read_storage::() + .get(scene_data.viewpoint_entity) + .map_or(false, |cs| cs.is_dodge()); - let up = match self.camera.get_mode() { - CameraMode::FirstPerson => { - if viewpoint_rolling { - viewpoint_height * 0.42 - } else if is_running && on_ground.unwrap_or(false) { - viewpoint_eye_height - + (scene_data.state.get_time() as f32 * 17.0).sin() * 0.05 - } else { - viewpoint_eye_height - } - }, - CameraMode::ThirdPerson if scene_data.is_aiming => viewpoint_height * 1.16, - CameraMode::ThirdPerson => viewpoint_eye_height, - CameraMode::Freefly => 0.0, + let is_running = ecs + .read_storage::() + .get(scene_data.viewpoint_entity) + .map(|v| v.0.magnitude_squared() > RUNNING_THRESHOLD.powi(2)) + .unwrap_or(false); + + let on_ground = ecs + .read_storage::() + .get(scene_data.viewpoint_entity) + .map(|p| p.on_ground.is_some()); + + let up = match self.camera.get_mode() { + CameraMode::FirstPerson => { + if viewpoint_rolling { + viewpoint_height * 0.42 + } else if is_running && on_ground.unwrap_or(false) { + viewpoint_eye_height + + (scene_data.state.get_time() as f32 * 17.0).sin() * 0.05 + } else { + viewpoint_eye_height + } + }, + CameraMode::ThirdPerson if scene_data.is_aiming => viewpoint_height * 1.16, + CameraMode::ThirdPerson => viewpoint_eye_height, + CameraMode::Freefly => 0.0, + }; + // Alter camera position to match player. + let tilt = self.camera.get_orientation().y; + let dist = self.camera.get_distance(); + + Vec3::unit_z() * (up - tilt.min(0.0).sin() * dist * 0.6) + } else { + self.figure_mgr + .viewpoint_offset(scene_data, scene_data.viewpoint_entity) }; match self.camera.get_mode() { CameraMode::FirstPerson | CameraMode::ThirdPerson => { - self.camera.set_focus_pos( - viewpoint_pos + Vec3::unit_z() * (up - tilt.min(0.0).sin() * dist * 0.6), - ); + self.camera.set_focus_pos(viewpoint_pos + viewpoint_offset); }, CameraMode::Freefly => {}, };