mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add quadruped_low skeleton
This commit is contained in:
parent
2a7a8b05e6
commit
72eb03ceb5
@ -561,5 +561,19 @@
|
||||
"generic": "Reddragon"
|
||||
}
|
||||
}
|
||||
},
|
||||
"quadruped_low": {
|
||||
"body": {
|
||||
"keyword": "quadruped_low",
|
||||
"names": [
|
||||
"Sobek"
|
||||
]
|
||||
},
|
||||
"species": {
|
||||
"crocodile": {
|
||||
"keyword": "crocodile",
|
||||
"generic": "Crocodile"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
assets/voxygen/voxel/npc/crocodile/female/chest_front.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/chest_front.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/female/chest_rear.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/chest_rear.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/female/foot_bl.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/foot_bl.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/female/foot_br.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/foot_br.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/female/foot_fl.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/foot_fl.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/female/foot_fr.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/foot_fr.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/female/head_lower.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/head_lower.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/female/head_upper.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/head_upper.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/female/jaw.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/jaw.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/female/tail.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/female/tail.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/chest_front.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/chest_front.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/chest_rear.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/chest_rear.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/foot_bl.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/foot_bl.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/foot_br.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/foot_br.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/foot_fl.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/foot_fl.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/foot_fr.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/foot_fr.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/head_lower.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/head_lower.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/head_upper.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/head_upper.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/jaw.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/jaw.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
assets/voxygen/voxel/npc/crocodile/male/tail.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/npc/crocodile/male/tail.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
62
assets/voxygen/voxel/quadruped_low_central_manifest.ron
Normal file
62
assets/voxygen/voxel/quadruped_low_central_manifest.ron
Normal file
@ -0,0 +1,62 @@
|
||||
({
|
||||
(Crocodile, Male): (
|
||||
upper: (
|
||||
offset: (-7.0, -9.0, -5.5),
|
||||
central: ("npc.crocodile.male.head_upper"),
|
||||
),
|
||||
lower: (
|
||||
offset: (-7.0, -4.5, -5.0),
|
||||
central: ("npc.crocodile.male.head_lower"),
|
||||
),
|
||||
jaw: (
|
||||
offset: (-3.0, -3.0, -2.5),
|
||||
central: ("npc.crocodile.male.jaw"),
|
||||
),
|
||||
chest_rear: (
|
||||
offset: (-8.0, -5.5, -6.0),
|
||||
central: ("npc.crocodile.male.chest_front"),
|
||||
),
|
||||
chest_front: (
|
||||
offset: (-8.0, -5.5, -6.0),
|
||||
central: ("npc.crocodile.male.chest_front"),
|
||||
),
|
||||
tail_rear: (
|
||||
offset: (-2.0, -9.5, -5.0),
|
||||
central: ("npc.crocodile.male.tail"),
|
||||
),
|
||||
tail_front: (
|
||||
offset: (-2.0, -9.5, -5.0),
|
||||
central: ("npc.crocodile.male.tail"),
|
||||
),
|
||||
),
|
||||
(Crocodile, Female): (
|
||||
upper: (
|
||||
offset: (-7.0, -9.0, -5.5),
|
||||
central: ("npc.crocodile.female.head_upper"),
|
||||
),
|
||||
lower: (
|
||||
offset: (-7.0, -4.5, -5.0),
|
||||
central: ("npc.crocodile.female.head_lower"),
|
||||
),
|
||||
jaw: (
|
||||
offset: (-3.0, -3.0, -2.5),
|
||||
central: ("npc.crocodile.female.jaw"),
|
||||
),
|
||||
chest_rear: (
|
||||
offset: (-8.0, -5.5, -6.0),
|
||||
central: ("npc.crocodile.female.chest_rear"),
|
||||
),
|
||||
chest_front: (
|
||||
offset: (-8.0, -5.5, -6.0),
|
||||
central: ("npc.crocodile.female.chest_front"),
|
||||
),
|
||||
tail_rear: (
|
||||
offset: (-2.0, -9.5, -5.0),
|
||||
central: ("npc.crocodile.female.tail"),
|
||||
),
|
||||
tail_front: (
|
||||
offset: (-2.0, -9.5, -5.0),
|
||||
central: ("npc.crocodile.female.tail"),
|
||||
),
|
||||
),
|
||||
})
|
38
assets/voxygen/voxel/quadruped_low_lateral_manifest.ron
Normal file
38
assets/voxygen/voxel/quadruped_low_lateral_manifest.ron
Normal file
@ -0,0 +1,38 @@
|
||||
({
|
||||
(Crocodile, Male): (
|
||||
front_left: (
|
||||
offset: (-2.5, -4.0, -1.5),
|
||||
lateral: ("npc.crocodile.male.foot_fl"),
|
||||
),
|
||||
front_right: (
|
||||
offset: (-2.5, -4.0, -1.5),
|
||||
lateral: ("npc.crocodile.male.foot_fr"),
|
||||
),
|
||||
back_left: (
|
||||
offset: (-2.5, -4.0, -3.0),
|
||||
lateral: ("npc.crocodile.male.foot_bl"),
|
||||
),
|
||||
back_right: (
|
||||
offset: (-2.5, -4.0, -3.0),
|
||||
lateral: ("npc.crocodile.male.foot_br"),
|
||||
),
|
||||
),
|
||||
(Crocodile, Female): (
|
||||
front_left: (
|
||||
offset: (-2.5, -4.0, -1.5),
|
||||
lateral: ("npc.crocodile.female.foot_fl"),
|
||||
),
|
||||
front_right: (
|
||||
offset: (-2.5, -4.0, -1.5),
|
||||
lateral: ("npc.crocodile.female.foot_fr"),
|
||||
),
|
||||
back_left: (
|
||||
offset: (-2.5, -4.0, -3.0),
|
||||
lateral: ("npc.crocodile.female.foot_bl"),
|
||||
),
|
||||
back_right: (
|
||||
offset: (-2.5, -4.0, -3.0),
|
||||
lateral: ("npc.crocodile.female.foot_br"),
|
||||
),
|
||||
),
|
||||
})
|
@ -10,6 +10,7 @@ pub mod humanoid;
|
||||
pub mod object;
|
||||
pub mod quadruped_medium;
|
||||
pub mod quadruped_small;
|
||||
pub mod quadruped_low;
|
||||
|
||||
use crate::{
|
||||
assets::{self, Asset},
|
||||
@ -34,6 +35,7 @@ pub enum Body {
|
||||
Object(object::Body) = 9,
|
||||
Golem(golem::Body) = 10,
|
||||
Critter(critter::Body) = 11,
|
||||
QuadrupedLow(quadruped_low::Body) = 12,
|
||||
}
|
||||
|
||||
/// Data representing data generic to the body together with per-species data.
|
||||
@ -61,6 +63,7 @@ pub struct AllBodies<BodyMeta, SpeciesMeta> {
|
||||
pub golem: BodyData<BodyMeta, golem::AllSpecies<SpeciesMeta>>,
|
||||
pub critter: BodyData<BodyMeta, critter::AllSpecies<SpeciesMeta>>,
|
||||
pub dragon: BodyData<BodyMeta, dragon::AllSpecies<SpeciesMeta>>,
|
||||
pub quadruped_low: BodyData<BodyMeta, quadruped_low::AllSpecies<SpeciesMeta>>,
|
||||
}
|
||||
|
||||
/// Can only retrieve body metadata by direct index.
|
||||
@ -78,6 +81,7 @@ impl<BodyMeta, SpeciesMeta> core::ops::Index<NpcKind> for AllBodies<BodyMeta, Sp
|
||||
NpcKind::StoneGolem => &self.golem.body,
|
||||
NpcKind::Rat => &self.critter.body,
|
||||
NpcKind::Reddragon => &self.dragon.body,
|
||||
NpcKind::Crocodile => &self.quadruped_low.body,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,6 +122,7 @@ impl Body {
|
||||
Body::FishSmall(_) => 0.2,
|
||||
Body::BipedLarge(_) => 2.0,
|
||||
Body::Golem(_) => 2.5,
|
||||
Body::QuadrupedLow(_) => 1.0,
|
||||
Body::Object(_) => 0.3,
|
||||
}
|
||||
}
|
||||
|
69
common/src/comp/body/quadruped_low.rs
Normal file
69
common/src/comp/body/quadruped_low.rs
Normal file
@ -0,0 +1,69 @@
|
||||
use rand::{seq::SliceRandom, thread_rng};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct Body {
|
||||
pub species: Species,
|
||||
pub body_type: BodyType,
|
||||
}
|
||||
|
||||
impl Body {
|
||||
pub fn random() -> Self {
|
||||
let mut rng = thread_rng();
|
||||
let species = *(&ALL_SPECIES).choose(&mut rng).unwrap();
|
||||
Self::random_with(&mut rng, &species)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn random_with(rng: &mut impl rand::Rng, &species: &Species) -> Self {
|
||||
let body_type = *(&ALL_BODY_TYPES).choose(rng).unwrap();
|
||||
Self { species, body_type }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Body> for super::Body {
|
||||
fn from(body: Body) -> Self { super::Body::QuadrupedLow(body) }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum Species {
|
||||
Crocodile = 0,
|
||||
}
|
||||
|
||||
/// Data representing per-species generic data.
|
||||
///
|
||||
/// NOTE: Deliberately don't (yet?) implement serialize.
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct AllSpecies<SpeciesMeta> {
|
||||
pub crocodile: SpeciesMeta,
|
||||
}
|
||||
|
||||
impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta> {
|
||||
type Output = SpeciesMeta;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, &index: &'a Species) -> &Self::Output {
|
||||
match index {
|
||||
Species::Crocodile => &self.crocodile,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const ALL_SPECIES: [Species; 1] = [
|
||||
Species::Crocodile,
|
||||
];
|
||||
|
||||
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
|
||||
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
|
||||
type Item = Species;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[repr(u32)]
|
||||
pub enum BodyType {
|
||||
Female = 0,
|
||||
Male = 1,
|
||||
}
|
||||
pub const ALL_BODY_TYPES: [BodyType; 2] = [BodyType::Female, BodyType::Male];
|
@ -23,7 +23,7 @@ pub use admin::{Admin, AdminList};
|
||||
pub use agent::{Agent, Alignment};
|
||||
pub use body::{
|
||||
biped_large, bird_medium, bird_small, critter, dragon, fish_medium, fish_small, golem,
|
||||
humanoid, object, quadruped_medium, quadruped_small, AllBodies, Body, BodyData,
|
||||
humanoid, object, quadruped_medium, quadruped_small, quadruped_low, AllBodies, Body, BodyData,
|
||||
};
|
||||
pub use character_state::{Attacking, CharacterState, StateUpdate};
|
||||
pub use chat::{ChatMode, ChatMsg, ChatType, Faction, Group, SpeechBubble, SpeechBubbleType};
|
||||
|
@ -108,6 +108,7 @@ impl EntityInfo {
|
||||
Some(get_npc_name(&NPC_NAMES.quadruped_small, body.species))
|
||||
},
|
||||
Body::Dragon(body) => Some(get_npc_name(&NPC_NAMES.dragon, body.species)),
|
||||
Body::QuadrupedLow(body) => Some(get_npc_name(&NPC_NAMES.quadruped_low, body.species)),
|
||||
_ => None,
|
||||
}
|
||||
.map(|s| {
|
||||
|
@ -16,9 +16,10 @@ pub enum NpcKind {
|
||||
Rat,
|
||||
StoneGolem,
|
||||
Reddragon,
|
||||
Crocodile,
|
||||
}
|
||||
|
||||
pub const ALL_NPCS: [NpcKind; 8] = [
|
||||
pub const ALL_NPCS: [NpcKind; 9] = [
|
||||
NpcKind::Humanoid,
|
||||
NpcKind::Wolf,
|
||||
NpcKind::Pig,
|
||||
@ -27,6 +28,7 @@ pub const ALL_NPCS: [NpcKind; 8] = [
|
||||
NpcKind::Rat,
|
||||
NpcKind::StoneGolem,
|
||||
NpcKind::Reddragon,
|
||||
NpcKind::Crocodile,
|
||||
];
|
||||
|
||||
/// Body-specific NPC name metadata.
|
||||
@ -94,6 +96,7 @@ pub fn kind_to_body(kind: NpcKind) -> Body {
|
||||
NpcKind::Rat => comp::critter::Body::random().into(),
|
||||
NpcKind::StoneGolem => comp::golem::Body::random().into(),
|
||||
NpcKind::Reddragon => comp::dragon::Body::random().into(),
|
||||
NpcKind::Crocodile => comp::quadruped_low::Body::random().into(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,6 +226,14 @@ impl NpcBody {
|
||||
comp::dragon::Body::random_with,
|
||||
)
|
||||
})
|
||||
.or_else(|| {
|
||||
parse(
|
||||
s,
|
||||
NpcKind::Crocodile,
|
||||
&npc_names.quadruped_low,
|
||||
comp::quadruped_low::Body::random_with,
|
||||
)
|
||||
})
|
||||
.ok_or(())
|
||||
}
|
||||
}
|
||||
|
76
voxygen/src/anim/mod.rs
Normal file
76
voxygen/src/anim/mod.rs
Normal file
@ -0,0 +1,76 @@
|
||||
pub mod biped_large;
|
||||
pub mod bird_medium;
|
||||
pub mod bird_small;
|
||||
pub mod character;
|
||||
pub mod critter;
|
||||
pub mod dragon;
|
||||
pub mod fish_medium;
|
||||
pub mod fish_small;
|
||||
pub mod fixture;
|
||||
pub mod golem;
|
||||
pub mod object;
|
||||
pub mod quadruped_medium;
|
||||
pub mod quadruped_small;
|
||||
pub mod quadruped_low;
|
||||
|
||||
use crate::render::FigureBoneData;
|
||||
use vek::*;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Bone {
|
||||
pub offset: Vec3<f32>,
|
||||
pub ori: Quaternion<f32>,
|
||||
pub scale: Vec3<f32>,
|
||||
}
|
||||
|
||||
impl Default for Bone {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
offset: Vec3::zero(),
|
||||
ori: Quaternion::identity(),
|
||||
scale: Vec3::broadcast(1.0 / 11.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Bone {
|
||||
pub fn compute_base_matrix(&self) -> Mat4<f32> {
|
||||
Mat4::<f32>::translation_3d(self.offset)
|
||||
* Mat4::scaling_3d(self.scale)
|
||||
* Mat4::from(self.ori)
|
||||
}
|
||||
|
||||
/// Change the current bone to be more like `target`.
|
||||
fn interpolate(&mut self, target: &Bone, dt: f32) {
|
||||
// TODO: Make configurable.
|
||||
let factor = (15.0 * dt).min(1.0);
|
||||
self.offset += (target.offset - self.offset) * factor;
|
||||
self.ori = vek::Slerp::slerp(self.ori, target.ori, factor);
|
||||
self.scale += (target.scale - self.scale) * factor;
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Skeleton: Send + Sync + 'static {
|
||||
type Attr;
|
||||
|
||||
fn bone_count(&self) -> usize { 16 }
|
||||
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>);
|
||||
|
||||
/// Change the current skeleton to be more like `target`.
|
||||
fn interpolate(&mut self, target: &Self, dt: f32);
|
||||
}
|
||||
|
||||
pub trait Animation {
|
||||
type Skeleton: Skeleton;
|
||||
type Dependency;
|
||||
|
||||
/// Returns a new skeleton that is generated by the animation.
|
||||
fn update_skeleton(
|
||||
skeleton: &Self::Skeleton,
|
||||
dependency: Self::Dependency,
|
||||
anim_time: f64,
|
||||
rate: &mut f32,
|
||||
skeleton_attr: &<<Self as Animation>::Skeleton as Skeleton>::Attr,
|
||||
) -> Self::Skeleton;
|
||||
}
|
116
voxygen/src/anim/quadruped_low/idle.rs
Normal file
116
voxygen/src/anim/quadruped_low/idle.rs
Normal file
@ -0,0 +1,116 @@
|
||||
use super::{super::Animation, QuadrupedLowSkeleton, SkeletonAttr};
|
||||
use std::{f32::consts::PI, ops::Mul};
|
||||
use vek::*;
|
||||
|
||||
pub struct IdleAnimation;
|
||||
|
||||
impl Animation for IdleAnimation {
|
||||
type Dependency = f64;
|
||||
type Skeleton = QuadrupedLowSkeleton;
|
||||
|
||||
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 ultra_slow = (anim_time as f32 * 1.0).sin();
|
||||
let slow = (anim_time as f32 * 2.5).sin();
|
||||
let slowalt = (anim_time as f32 * 2.5 + PI / 2.0).sin();
|
||||
|
||||
let dragon_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.head_upper.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.head_upper.0,
|
||||
skeleton_attr.head_upper.1 + ultra_slow * 0.20,
|
||||
);
|
||||
next.head_upper.ori = Quaternion::rotation_z(0.8 * dragon_look.x)
|
||||
* Quaternion::rotation_x(0.8 * dragon_look.y);
|
||||
next.head_upper.scale = Vec3::one();
|
||||
|
||||
next.head_lower.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.head_lower.0,
|
||||
skeleton_attr.head_lower.1 + ultra_slow * 0.20,
|
||||
);
|
||||
next.head_lower.ori = Quaternion::rotation_z(0.8 * dragon_look.x)
|
||||
* Quaternion::rotation_x(-0.2 + 0.8 * dragon_look.y);
|
||||
next.head_lower.scale = Vec3::one() * 1.05;
|
||||
|
||||
next.jaw.offset = Vec3::new(0.0, skeleton_attr.jaw.0, skeleton_attr.jaw.1);
|
||||
next.jaw.ori = Quaternion::rotation_x(slow * 0.04);
|
||||
next.jaw.scale = Vec3::one() * 1.05;
|
||||
|
||||
next.chest_front.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.chest_front.0,
|
||||
skeleton_attr.chest_front.1,
|
||||
);
|
||||
next.chest_front.ori = Quaternion::rotation_y(slow * 0.01);
|
||||
next.chest_front.scale = Vec3::one() * 1.05;
|
||||
|
||||
next.chest_rear.offset =
|
||||
Vec3::new(0.0, skeleton_attr.chest_rear.0, skeleton_attr.chest_rear.1);
|
||||
next.chest_rear.ori = Quaternion::rotation_y(slow * 0.01);
|
||||
next.chest_rear.scale = Vec3::one() * 1.05;
|
||||
|
||||
next.tail_front.offset =
|
||||
Vec3::new(0.0, skeleton_attr.tail_front.0, skeleton_attr.tail_front.1);
|
||||
next.tail_front.ori = Quaternion::rotation_z(slowalt * 0.10) * Quaternion::rotation_x(0.1);
|
||||
next.tail_front.scale = Vec3::one() * 0.98;
|
||||
|
||||
next.tail_rear.offset =
|
||||
Vec3::new(0.0, skeleton_attr.tail_rear.0, skeleton_attr.tail_rear.1);
|
||||
next.tail_rear.ori = Quaternion::rotation_z(slowalt * 0.12) * Quaternion::rotation_x(0.05);
|
||||
next.tail_rear.scale = Vec3::one() * 0.98;
|
||||
|
||||
next.foot_fl.offset = Vec3::new(
|
||||
-skeleton_attr.feet_f.0,
|
||||
skeleton_attr.feet_f.1,
|
||||
skeleton_attr.feet_f.2,
|
||||
);
|
||||
next.foot_fl.ori = Quaternion::rotation_x(0.0);
|
||||
next.foot_fl.scale = Vec3::one();
|
||||
|
||||
next.foot_fr.offset = Vec3::new(
|
||||
skeleton_attr.feet_f.0,
|
||||
skeleton_attr.feet_f.1,
|
||||
skeleton_attr.feet_f.2,
|
||||
);
|
||||
next.foot_fr.ori = Quaternion::rotation_x(0.0);
|
||||
next.foot_fr.scale = Vec3::one();
|
||||
|
||||
next.foot_bl.offset = Vec3::new(
|
||||
-skeleton_attr.feet_b.0,
|
||||
skeleton_attr.feet_b.1,
|
||||
skeleton_attr.feet_b.2,
|
||||
);
|
||||
next.foot_bl.ori = Quaternion::rotation_x(0.0);
|
||||
next.foot_bl.scale = Vec3::one();
|
||||
|
||||
next.foot_br.offset = Vec3::new(
|
||||
skeleton_attr.feet_b.0,
|
||||
skeleton_attr.feet_b.1,
|
||||
skeleton_attr.feet_b.2,
|
||||
);
|
||||
next.foot_br.ori = Quaternion::rotation_x(0.0);
|
||||
next.foot_br.scale = Vec3::one();
|
||||
|
||||
next
|
||||
}
|
||||
}
|
121
voxygen/src/anim/quadruped_low/jump.rs
Normal file
121
voxygen/src/anim/quadruped_low/jump.rs
Normal file
@ -0,0 +1,121 @@
|
||||
use super::{super::Animation, QuadrupedLowSkeleton, SkeletonAttr};
|
||||
use std::f32::consts::PI;
|
||||
use vek::*;
|
||||
|
||||
pub struct JumpAnimation;
|
||||
|
||||
impl Animation for JumpAnimation {
|
||||
type Dependency = (f32, f64);
|
||||
type Skeleton = QuadrupedLowSkeleton;
|
||||
|
||||
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 lab = 12.0;
|
||||
|
||||
let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin();
|
||||
let wave_ultra_slow_cos = (anim_time as f32 * 3.0 + PI).cos();
|
||||
let wave_slow = (anim_time as f32 * 3.5 + PI).sin();
|
||||
|
||||
let footl = (anim_time as f32 * lab as f32 + PI).sin();
|
||||
let footr = (anim_time as f32 * lab as f32).sin();
|
||||
|
||||
let center = (anim_time as f32 * lab as f32 + PI / 2.0).sin();
|
||||
let centeroffset = (anim_time as f32 * lab as f32 + PI * 1.5).sin();
|
||||
|
||||
next.head_upper.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.head_upper.0,
|
||||
skeleton_attr.head_upper.1 + wave_ultra_slow * 0.20,
|
||||
);
|
||||
next.head_upper.ori =
|
||||
Quaternion::rotation_z(0.0) * Quaternion::rotation_x(wave_ultra_slow * -0.10);
|
||||
next.head_upper.scale = Vec3::one() * 1.05;
|
||||
|
||||
next.head_lower.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.head_lower.0,
|
||||
skeleton_attr.head_lower.1 + wave_ultra_slow * 0.20,
|
||||
);
|
||||
next.head_lower.ori =
|
||||
Quaternion::rotation_z(0.0) * Quaternion::rotation_x(wave_ultra_slow * -0.10);
|
||||
next.head_lower.scale = Vec3::one() * 1.05;
|
||||
|
||||
next.jaw.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.jaw.0 - wave_ultra_slow_cos * 0.12,
|
||||
skeleton_attr.jaw.1 + wave_slow * 0.2,
|
||||
);
|
||||
next.jaw.ori = Quaternion::rotation_x(wave_slow * 0.03);
|
||||
next.jaw.scale = Vec3::one() * 1.05;
|
||||
|
||||
next.tail_front.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.tail_front.0,
|
||||
skeleton_attr.tail_front.1 + centeroffset * 0.6,
|
||||
);
|
||||
next.tail_front.ori = Quaternion::rotation_x(center * 0.03);
|
||||
next.tail_front.scale = Vec3::one() * 0.98;
|
||||
|
||||
next.tail_rear.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.tail_rear.0,
|
||||
skeleton_attr.tail_rear.1 + centeroffset * 0.6,
|
||||
);
|
||||
next.tail_rear.ori = Quaternion::rotation_x(center * 0.03);
|
||||
next.tail_rear.scale = Vec3::one() * 0.98;
|
||||
|
||||
next.chest_front.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.chest_front.0,
|
||||
skeleton_attr.chest_front.1,
|
||||
);
|
||||
next.chest_front.ori = Quaternion::rotation_y(center * 0.05);
|
||||
next.chest_front.scale = Vec3::one();
|
||||
|
||||
next.chest_rear.offset =
|
||||
Vec3::new(0.0, skeleton_attr.chest_rear.0, skeleton_attr.chest_rear.1);
|
||||
next.chest_rear.ori = Quaternion::rotation_y(center * 0.05);
|
||||
next.chest_rear.scale = Vec3::one();
|
||||
|
||||
next.foot_fl.offset = Vec3::new(
|
||||
-skeleton_attr.feet_f.0,
|
||||
skeleton_attr.feet_f.1,
|
||||
skeleton_attr.feet_f.2,
|
||||
);
|
||||
next.foot_fl.ori = Quaternion::rotation_x(-1.3 + footl * 0.06);
|
||||
next.foot_fl.scale = Vec3::one();
|
||||
|
||||
next.foot_fr.offset = Vec3::new(
|
||||
skeleton_attr.feet_f.0,
|
||||
skeleton_attr.feet_f.1,
|
||||
skeleton_attr.feet_f.2,
|
||||
);
|
||||
next.foot_fr.ori = Quaternion::rotation_x(-1.3 + footr * 0.06);
|
||||
next.foot_fr.scale = Vec3::one();
|
||||
|
||||
next.foot_bl.offset = Vec3::new(
|
||||
-skeleton_attr.feet_b.0,
|
||||
skeleton_attr.feet_b.1,
|
||||
skeleton_attr.feet_b.2,
|
||||
);
|
||||
next.foot_bl.ori = Quaternion::rotation_x(-1.3 + footl * 0.06);
|
||||
next.foot_bl.scale = Vec3::one();
|
||||
|
||||
next.foot_br.offset = Vec3::new(
|
||||
skeleton_attr.feet_b.0,
|
||||
skeleton_attr.feet_b.1,
|
||||
skeleton_attr.feet_b.2,
|
||||
);
|
||||
next.foot_br.ori = Quaternion::rotation_x(-1.3 + footr * 0.06);
|
||||
next.foot_br.scale = Vec3::one();
|
||||
|
||||
next
|
||||
}
|
||||
}
|
167
voxygen/src/anim/quadruped_low/mod.rs
Normal file
167
voxygen/src/anim/quadruped_low/mod.rs
Normal file
@ -0,0 +1,167 @@
|
||||
pub mod idle;
|
||||
pub mod jump;
|
||||
pub mod run;
|
||||
|
||||
// Reexports
|
||||
pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
|
||||
|
||||
use super::{Bone, Skeleton};
|
||||
use crate::render::FigureBoneData;
|
||||
use common::comp::{self};
|
||||
use vek::Vec3;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct QuadrupedLowSkeleton {
|
||||
head_upper: Bone,
|
||||
head_lower: Bone,
|
||||
jaw: Bone,
|
||||
tail_front: Bone,
|
||||
tail_rear: Bone,
|
||||
chest_front: Bone,
|
||||
chest_rear: Bone,
|
||||
foot_fl: Bone,
|
||||
foot_fr: Bone,
|
||||
foot_bl: Bone,
|
||||
foot_br: Bone,
|
||||
}
|
||||
|
||||
impl QuadrupedLowSkeleton {
|
||||
pub fn new() -> Self { Self::default() }
|
||||
}
|
||||
|
||||
impl Skeleton for QuadrupedLowSkeleton {
|
||||
type Attr = SkeletonAttr;
|
||||
|
||||
fn bone_count(&self) -> usize { 11 }
|
||||
|
||||
fn compute_matrices(&self) -> ([FigureBoneData; 16], Vec3<f32>) {
|
||||
let head_upper_mat = self.head_upper.compute_base_matrix();
|
||||
let head_lower_mat = self.head_lower.compute_base_matrix();
|
||||
let chest_front_mat = self.chest_front.compute_base_matrix();
|
||||
let chest_rear_mat = self.chest_rear.compute_base_matrix();
|
||||
(
|
||||
[
|
||||
FigureBoneData::new(chest_front_mat * head_lower_mat * head_upper_mat),
|
||||
FigureBoneData::new(chest_front_mat * head_lower_mat),
|
||||
FigureBoneData::new(
|
||||
chest_front_mat
|
||||
* head_lower_mat
|
||||
* head_upper_mat
|
||||
* self.jaw.compute_base_matrix(),
|
||||
),
|
||||
FigureBoneData::new(chest_front_mat),
|
||||
FigureBoneData::new(chest_front_mat * self.chest_rear.compute_base_matrix()),
|
||||
FigureBoneData::new(chest_front_mat * chest_rear_mat * self.tail_front.compute_base_matrix()),
|
||||
FigureBoneData::new(
|
||||
chest_front_mat
|
||||
* chest_rear_mat
|
||||
* self.tail_front.compute_base_matrix()
|
||||
* self.tail_rear.compute_base_matrix(),
|
||||
),
|
||||
FigureBoneData::new(self.foot_fl.compute_base_matrix()),
|
||||
FigureBoneData::new(self.foot_fr.compute_base_matrix()),
|
||||
FigureBoneData::new(self.foot_bl.compute_base_matrix()),
|
||||
FigureBoneData::new(self.foot_br.compute_base_matrix()),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
FigureBoneData::default(),
|
||||
],
|
||||
Vec3::default(),
|
||||
)
|
||||
}
|
||||
|
||||
fn interpolate(&mut self, target: &Self, dt: f32) {
|
||||
self.head_upper.interpolate(&target.head_upper, dt);
|
||||
self.head_lower.interpolate(&target.head_lower, dt);
|
||||
self.jaw.interpolate(&target.jaw, dt);
|
||||
self.tail_front.interpolate(&target.tail_front, dt);
|
||||
self.tail_rear.interpolate(&target.tail_rear, dt);
|
||||
self.chest_front.interpolate(&target.chest_front, dt);
|
||||
self.chest_rear.interpolate(&target.chest_rear, dt);
|
||||
self.foot_fl.interpolate(&target.foot_fl, dt);
|
||||
self.foot_fr.interpolate(&target.foot_fr, dt);
|
||||
self.foot_bl.interpolate(&target.foot_bl, dt);
|
||||
self.foot_br.interpolate(&target.foot_br, dt);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SkeletonAttr {
|
||||
head_upper: (f32, f32),
|
||||
head_lower: (f32, f32),
|
||||
jaw: (f32, f32),
|
||||
tail_front: (f32, f32),
|
||||
tail_rear: (f32, f32),
|
||||
chest_front: (f32, f32),
|
||||
chest_rear: (f32, f32),
|
||||
feet_f: (f32, f32, f32),
|
||||
feet_b: (f32, f32, f32),
|
||||
height: f32,
|
||||
}
|
||||
|
||||
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
|
||||
match body {
|
||||
comp::Body::QuadrupedLow(body) => Ok(SkeletonAttr::from(body)),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SkeletonAttr {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
head_upper: (0.0, 0.0),
|
||||
head_lower: (0.0, 0.0),
|
||||
jaw: (0.0, 0.0),
|
||||
tail_front: (0.0, 0.0),
|
||||
tail_rear: (0.0, 0.0),
|
||||
chest_front: (0.0, 0.0),
|
||||
chest_rear: (0.0, 0.0),
|
||||
feet_f: (0.0, 0.0, 0.0),
|
||||
feet_b: (0.0, 0.0, 0.0),
|
||||
height: (0.0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a comp::quadruped_low::Body> for SkeletonAttr {
|
||||
fn from(body: &'a comp::quadruped_low::Body) -> Self {
|
||||
use comp::quadruped_low::Species::*;
|
||||
Self {
|
||||
head_upper: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (12.0, 16.0),
|
||||
},
|
||||
head_lower: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (-4.0, -7.0),
|
||||
},
|
||||
jaw: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (3.0, -5.0),
|
||||
},
|
||||
tail_rear: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (-6.0, -2.0),
|
||||
},
|
||||
tail_front: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (-6.0, -2.0),
|
||||
},
|
||||
chest_front: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (4.0, 11.0),
|
||||
},
|
||||
chest_rear: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (4.0, 11.0),
|
||||
},
|
||||
feet_f: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (5.0, 6.0, 2.0),
|
||||
},
|
||||
feet_b: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (5.0, -4.0, 3.0),
|
||||
},
|
||||
height: match (body.species, body.body_type) {
|
||||
(Crocodile, _) => (1.2),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
136
voxygen/src/anim/quadruped_low/run.rs
Normal file
136
voxygen/src/anim/quadruped_low/run.rs
Normal file
@ -0,0 +1,136 @@
|
||||
use super::{super::Animation, QuadrupedLowSkeleton, SkeletonAttr};
|
||||
use std::{f32::consts::PI, ops::Mul};
|
||||
use vek::*;
|
||||
|
||||
pub struct RunAnimation;
|
||||
|
||||
impl Animation for RunAnimation {
|
||||
type Dependency = (f32, f64);
|
||||
type Skeleton = QuadrupedLowSkeleton;
|
||||
|
||||
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 lab = 14;
|
||||
|
||||
let wave_ultra_slow_cos = (anim_time as f32 * 3.0 + PI).cos();
|
||||
let wave_slow = (anim_time as f32 * 4.5).sin();
|
||||
|
||||
let vertlf = (anim_time as f32 * lab as f32 + PI * 1.8).sin().max(0.15);
|
||||
let vertrfoffset = (anim_time as f32 * lab as f32 + PI * 0.80).sin().max(0.15);
|
||||
let vertlboffset = (anim_time as f32 * lab as f32).sin().max(0.15);
|
||||
let vertrb = (anim_time as f32 * lab as f32 + PI).sin().max(0.15);
|
||||
|
||||
let horilf = (anim_time as f32 * lab as f32 + PI * 1.2).sin();
|
||||
let horirfoffset = (anim_time as f32 * lab as f32 + PI * 0.20).sin();
|
||||
let horilboffset = (anim_time as f32 * lab as f32 + PI * 1.4).sin();
|
||||
let horirb = (anim_time as f32 * lab as f32 + PI * 0.4).sin();
|
||||
|
||||
let vertchest = (anim_time as f32 * lab as f32 + PI * 0.3).sin().max(0.2);
|
||||
let horichest = (anim_time as f32 * lab as f32 + PI * 0.8).sin();
|
||||
|
||||
let center = (anim_time as f32 * lab as f32 + PI / 2.0).sin();
|
||||
let centeroffset = (anim_time as f32 * lab as f32 + PI * 1.5).sin();
|
||||
|
||||
let dragon_look = Vec2::new(
|
||||
((global_time + anim_time) as f32 / 4.0)
|
||||
.floor()
|
||||
.mul(7331.0)
|
||||
.sin()
|
||||
* 0.25,
|
||||
((global_time + anim_time) as f32 / 4.0)
|
||||
.floor()
|
||||
.mul(1337.0)
|
||||
.sin()
|
||||
* 0.125,
|
||||
);
|
||||
|
||||
next.head_upper.offset =
|
||||
Vec3::new(0.0, skeleton_attr.head_upper.0, skeleton_attr.head_upper.1);
|
||||
next.head_upper.ori =
|
||||
Quaternion::rotation_x(dragon_look.y) * Quaternion::rotation_z(dragon_look.x);
|
||||
next.head_upper.scale = Vec3::one();
|
||||
|
||||
next.head_lower.offset =
|
||||
Vec3::new(0.0, skeleton_attr.head_lower.0, skeleton_attr.head_lower.1);
|
||||
next.head_lower.ori = Quaternion::rotation_x(wave_slow * 0.05);
|
||||
next.head_lower.scale = Vec3::one();
|
||||
|
||||
next.jaw.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.jaw.0 - wave_ultra_slow_cos * 0.12,
|
||||
skeleton_attr.jaw.1 + wave_slow * 0.2,
|
||||
);
|
||||
next.jaw.ori = Quaternion::rotation_x(wave_slow * 0.03);
|
||||
next.jaw.scale = Vec3::one() * 1.05;
|
||||
|
||||
next.tail_front.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.tail_front.0,
|
||||
skeleton_attr.tail_front.1 + centeroffset * 0.6,
|
||||
);
|
||||
next.tail_front.ori = Quaternion::rotation_x(center * 0.03);
|
||||
next.tail_front.scale = Vec3::one() * 0.98;
|
||||
|
||||
next.tail_rear.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.tail_rear.0,
|
||||
skeleton_attr.tail_rear.1 + centeroffset * 0.6,
|
||||
);
|
||||
next.tail_rear.ori = Quaternion::rotation_x(center * 0.03);
|
||||
next.tail_rear.scale = Vec3::one() * 0.98;
|
||||
|
||||
next.chest_front.offset = Vec3::new(
|
||||
0.0,
|
||||
skeleton_attr.chest_front.0 + horichest * 1.25,
|
||||
skeleton_attr.chest_front.1 + vertchest * -1.6 + 1.0,
|
||||
);
|
||||
next.chest_front.ori = Quaternion::rotation_y(horichest * -0.09);
|
||||
next.chest_front.scale = Vec3::one();
|
||||
|
||||
next.chest_rear.offset =
|
||||
Vec3::new(0.0, skeleton_attr.chest_rear.0, skeleton_attr.chest_rear.1);
|
||||
next.chest_rear.ori = Quaternion::rotation_y(horichest * -0.09);
|
||||
next.chest_rear.scale = Vec3::one();
|
||||
|
||||
next.foot_fl.offset = Vec3::new(
|
||||
-skeleton_attr.feet_f.0,
|
||||
skeleton_attr.feet_f.1 + horilf * 2.5,
|
||||
skeleton_attr.feet_f.2 + vertlf * 5.0 * skeleton_attr.height - 0.5,
|
||||
);
|
||||
next.foot_fl.ori = Quaternion::rotation_x(horilf * 0.4);
|
||||
next.foot_fl.scale = Vec3::one();
|
||||
|
||||
next.foot_fr.offset = Vec3::new(
|
||||
skeleton_attr.feet_f.0,
|
||||
skeleton_attr.feet_f.1 + horirfoffset * 2.5,
|
||||
skeleton_attr.feet_f.2 + vertrfoffset * 5.0 * skeleton_attr.height - 0.5,
|
||||
);
|
||||
next.foot_fr.ori = Quaternion::rotation_x(horirfoffset * 0.4);
|
||||
next.foot_fr.scale = Vec3::one();
|
||||
|
||||
next.foot_bl.offset = Vec3::new(
|
||||
-skeleton_attr.feet_b.0,
|
||||
skeleton_attr.feet_b.1 + horilboffset * 3.0,
|
||||
skeleton_attr.feet_b.2 + vertlboffset * 5.0 * skeleton_attr.height - 0.5,
|
||||
);
|
||||
next.foot_bl.ori = Quaternion::rotation_x(horilboffset * 0.35);
|
||||
next.foot_bl.scale = Vec3::one();
|
||||
|
||||
next.foot_br.offset = Vec3::new(
|
||||
skeleton_attr.feet_b.0,
|
||||
skeleton_attr.feet_b.1 + horirb * 3.0,
|
||||
skeleton_attr.feet_b.2 + vertrb * 5.0 * skeleton_attr.height - 0.5,
|
||||
);
|
||||
next.foot_br.ori = Quaternion::rotation_x(horirb * 0.35);
|
||||
next.foot_br.scale = Vec3::one();
|
||||
|
||||
next
|
||||
}
|
||||
}
|
@ -678,6 +678,75 @@ impl<Skel: Skeleton> FigureModelCache<Skel> {
|
||||
None,
|
||||
]
|
||||
},
|
||||
Body::QuadrupedLow(body) => {
|
||||
let quadruped_low_central_spec =
|
||||
QuadrupedLowCentralSpec::load_watched(manifest_indicator);
|
||||
let quadruped_low_lateral_spec =
|
||||
QuadrupedLowLateralSpec::load_watched(manifest_indicator);
|
||||
|
||||
[
|
||||
Some(quadruped_low_central_spec.mesh_head_upper(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_central_spec.mesh_head_lower(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_central_spec.mesh_jaw(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_central_spec.mesh_tail_front(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_central_spec.mesh_tail_rear(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_central_spec.mesh_chest_front(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_central_spec.mesh_chest_rear(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_lateral_spec.mesh_foot_fl(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_lateral_spec.mesh_foot_fr(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_lateral_spec.mesh_foot_bl(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
Some(quadruped_low_lateral_spec.mesh_foot_br(
|
||||
body.species,
|
||||
body.body_type,
|
||||
generate_mesh,
|
||||
)),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
]
|
||||
},
|
||||
Body::Object(object) => [
|
||||
Some(mesh_object(object, generate_mesh)),
|
||||
None,
|
||||
|
@ -18,6 +18,7 @@ use common::{
|
||||
object,
|
||||
quadruped_medium::{BodyType as QMBodyType, Species as QMSpecies},
|
||||
quadruped_small::{BodyType as QSBodyType, Species as QSSpecies},
|
||||
quadruped_low::{BodyType as QLBodyType, Species as QLSpecies},
|
||||
Loadout,
|
||||
},
|
||||
figure::{DynaUnionizer, MatSegment, Material, Segment},
|
||||
@ -2951,6 +2952,306 @@ impl GolemLateralSpec {
|
||||
generate_mesh(&lateral, Vec3::from(spec.foot_r.offset))
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct QuadrupedLowCentralSpec(HashMap<(QLSpecies, QLBodyType), SidedQLCentralVoxSpec>);
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct SidedQLCentralVoxSpec {
|
||||
upper: QuadrupedLowCentralSubSpec,
|
||||
lower: QuadrupedLowCentralSubSpec,
|
||||
jaw: QuadrupedLowCentralSubSpec,
|
||||
chest_front: QuadrupedLowCentralSubSpec,
|
||||
chest_rear: QuadrupedLowCentralSubSpec,
|
||||
tail_front: QuadrupedLowCentralSubSpec,
|
||||
tail_rear: QuadrupedLowCentralSubSpec,
|
||||
}
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct QuadrupedLowCentralSubSpec {
|
||||
offset: [f32; 3], // Should be relative to initial origin
|
||||
central: VoxSimple,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct QuadrupedLowLateralSpec(HashMap<(QLSpecies, QLBodyType), SidedQLLateralVoxSpec>);
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct SidedQLLateralVoxSpec {
|
||||
front_left: QuadrupedLowLateralSubSpec,
|
||||
front_right: QuadrupedLowLateralSubSpec,
|
||||
back_left: QuadrupedLowLateralSubSpec,
|
||||
back_right: QuadrupedLowLateralSubSpec,
|
||||
}
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct QuadrupedLowLateralSubSpec {
|
||||
offset: [f32; 3], // Should be relative to initial origin
|
||||
lateral: VoxSimple,
|
||||
}
|
||||
|
||||
impl Asset for QuadrupedLowCentralSpec {
|
||||
const ENDINGS: &'static [&'static str] = &["ron"];
|
||||
|
||||
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
|
||||
ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
|
||||
}
|
||||
}
|
||||
|
||||
impl Asset for QuadrupedLowLateralSpec {
|
||||
const ENDINGS: &'static [&'static str] = &["ron"];
|
||||
|
||||
fn parse(buf_reader: BufReader<File>) -> Result<Self, assets::Error> {
|
||||
ron::de::from_reader(buf_reader).map_err(assets::Error::parse_error)
|
||||
}
|
||||
}
|
||||
|
||||
impl QuadrupedLowCentralSpec {
|
||||
pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc<Self> {
|
||||
assets::load_watched::<Self>("voxygen.voxel.quadruped_low_central_manifest", indicator)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn mesh_head_upper(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No upper head 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 central = graceful_load_segment(&spec.upper.central.0);
|
||||
|
||||
generate_mesh(¢ral, Vec3::from(spec.upper.offset))
|
||||
}
|
||||
|
||||
pub fn mesh_head_lower(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No lower head 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 central = graceful_load_segment(&spec.lower.central.0);
|
||||
|
||||
generate_mesh(¢ral, Vec3::from(spec.lower.offset))
|
||||
}
|
||||
|
||||
pub fn mesh_jaw(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
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 central = graceful_load_segment(&spec.jaw.central.0);
|
||||
|
||||
generate_mesh(¢ral, Vec3::from(spec.jaw.offset))
|
||||
}
|
||||
|
||||
pub fn mesh_chest_front(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No chest_front 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 central = graceful_load_segment(&spec.chest_front.central.0);
|
||||
|
||||
generate_mesh(¢ral, Vec3::from(spec.chest_front.offset))
|
||||
}
|
||||
|
||||
pub fn mesh_chest_rear(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No chest_rear 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 central = graceful_load_segment(&spec.chest_rear.central.0);
|
||||
|
||||
generate_mesh(¢ral, Vec3::from(spec.chest_rear.offset))
|
||||
}
|
||||
|
||||
pub fn mesh_tail_rear(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No tail_rear 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 central = graceful_load_segment(&spec.tail_rear.central.0);
|
||||
|
||||
generate_mesh(¢ral, Vec3::from(spec.tail_rear.offset))
|
||||
}
|
||||
|
||||
pub fn mesh_tail_front(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No tail_front 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 central = graceful_load_segment(&spec.tail_front.central.0);
|
||||
|
||||
generate_mesh(¢ral, Vec3::from(spec.tail_front.offset))
|
||||
}
|
||||
}
|
||||
|
||||
impl QuadrupedLowLateralSpec {
|
||||
pub fn load_watched(indicator: &mut ReloadIndicator) -> Arc<Self> {
|
||||
assets::load_watched::<Self>("voxygen.voxel.quadruped_low_lateral_manifest", indicator)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn mesh_foot_fl(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No foot 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 lateral = graceful_load_segment(&spec.front_left.lateral.0);
|
||||
|
||||
generate_mesh(&lateral, Vec3::from(spec.front_left.offset))
|
||||
}
|
||||
|
||||
pub fn mesh_foot_fr(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No foot 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 lateral = graceful_load_segment(&spec.front_right.lateral.0);
|
||||
|
||||
generate_mesh(&lateral, Vec3::from(spec.front_right.offset))
|
||||
}
|
||||
|
||||
pub fn mesh_foot_bl(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No foot 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 lateral = graceful_load_segment(&spec.back_left.lateral.0);
|
||||
|
||||
generate_mesh(&lateral, Vec3::from(spec.back_left.offset))
|
||||
}
|
||||
|
||||
pub fn mesh_foot_br(
|
||||
&self,
|
||||
species: QLSpecies,
|
||||
body_type: QLBodyType,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
) -> Mesh<FigurePipeline> {
|
||||
let spec = match self.0.get(&(species, body_type)) {
|
||||
Some(spec) => spec,
|
||||
None => {
|
||||
error!(
|
||||
"No foot 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 lateral = graceful_load_segment(&spec.back_right.lateral.0);
|
||||
|
||||
generate_mesh(&lateral, Vec3::from(spec.back_right.offset))
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
pub fn mesh_object(
|
||||
obj: object::Body,
|
||||
generate_mesh: impl FnOnce(&Segment, Vec3<f32>) -> Mesh<FigurePipeline>,
|
||||
|
@ -5,6 +5,13 @@ pub use cache::FigureModelCache;
|
||||
pub use load::load_mesh; // TODO: Don't make this public.
|
||||
|
||||
use crate::{
|
||||
anim::{
|
||||
self, biped_large::BipedLargeSkeleton, bird_medium::BirdMediumSkeleton,
|
||||
bird_small::BirdSmallSkeleton, character::CharacterSkeleton, critter::CritterSkeleton,
|
||||
dragon::DragonSkeleton, fish_medium::FishMediumSkeleton, fish_small::FishSmallSkeleton,
|
||||
golem::GolemSkeleton, object::ObjectSkeleton, quadruped_medium::QuadrupedMediumSkeleton,
|
||||
quadruped_small::QuadrupedSmallSkeleton, quadruped_low::QuadrupedLowSkeleton, Animation, Skeleton,
|
||||
},
|
||||
ecs::comp::Interpolated,
|
||||
render::{Consts, FigureBoneData, FigureLocals, Globals, Light, Renderer, Shadow},
|
||||
scene::{
|
||||
@ -44,6 +51,7 @@ pub struct FigureMgr {
|
||||
critter_model_cache: FigureModelCache<CritterSkeleton>,
|
||||
quadruped_small_model_cache: FigureModelCache<QuadrupedSmallSkeleton>,
|
||||
quadruped_medium_model_cache: FigureModelCache<QuadrupedMediumSkeleton>,
|
||||
quadruped_low_model_cache: FigureModelCache<QuadrupedLowSkeleton>,
|
||||
bird_medium_model_cache: FigureModelCache<BirdMediumSkeleton>,
|
||||
bird_small_model_cache: FigureModelCache<BirdSmallSkeleton>,
|
||||
dragon_model_cache: FigureModelCache<DragonSkeleton>,
|
||||
@ -54,6 +62,7 @@ pub struct FigureMgr {
|
||||
character_states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
|
||||
quadruped_small_states: HashMap<EcsEntity, FigureState<QuadrupedSmallSkeleton>>,
|
||||
quadruped_medium_states: HashMap<EcsEntity, FigureState<QuadrupedMediumSkeleton>>,
|
||||
quadruped_low_states: HashMap<EcsEntity, FigureState<QuadrupedLowSkeleton>>,
|
||||
bird_medium_states: HashMap<EcsEntity, FigureState<BirdMediumSkeleton>>,
|
||||
fish_medium_states: HashMap<EcsEntity, FigureState<FishMediumSkeleton>>,
|
||||
critter_states: HashMap<EcsEntity, FigureState<CritterSkeleton>>,
|
||||
@ -73,6 +82,7 @@ impl FigureMgr {
|
||||
critter_model_cache: FigureModelCache::new(),
|
||||
quadruped_small_model_cache: FigureModelCache::new(),
|
||||
quadruped_medium_model_cache: FigureModelCache::new(),
|
||||
quadruped_low_model_cache: FigureModelCache::new(),
|
||||
bird_medium_model_cache: FigureModelCache::new(),
|
||||
bird_small_model_cache: FigureModelCache::new(),
|
||||
dragon_model_cache: FigureModelCache::new(),
|
||||
@ -83,6 +93,7 @@ impl FigureMgr {
|
||||
character_states: HashMap::new(),
|
||||
quadruped_small_states: HashMap::new(),
|
||||
quadruped_medium_states: HashMap::new(),
|
||||
quadruped_low_states: HashMap::new(),
|
||||
bird_medium_states: HashMap::new(),
|
||||
fish_medium_states: HashMap::new(),
|
||||
critter_states: HashMap::new(),
|
||||
@ -100,6 +111,7 @@ impl FigureMgr {
|
||||
self.critter_model_cache.clean(tick);
|
||||
self.quadruped_small_model_cache.clean(tick);
|
||||
self.quadruped_medium_model_cache.clean(tick);
|
||||
self.quadruped_low_model_cache.clean(tick);
|
||||
self.bird_medium_model_cache.clean(tick);
|
||||
self.bird_small_model_cache.clean(tick);
|
||||
self.dragon_model_cache.clean(tick);
|
||||
@ -261,6 +273,9 @@ impl FigureMgr {
|
||||
Body::QuadrupedMedium(_) => {
|
||||
self.quadruped_medium_states.remove(&entity);
|
||||
},
|
||||
Body::QuadrupedLow(_) => {
|
||||
self.quadruped_low_states.remove(&entity);
|
||||
},
|
||||
Body::BirdMedium(_) => {
|
||||
self.bird_medium_states.remove(&entity);
|
||||
},
|
||||
@ -307,6 +322,11 @@ impl FigureMgr {
|
||||
.get_mut(&entity)
|
||||
.map(|state| state.visible = false);
|
||||
},
|
||||
Body::QuadrupedLow(_) => {
|
||||
self.quadruped_low_states
|
||||
.get_mut(&entity)
|
||||
.map(|state| state.visible = false);
|
||||
},
|
||||
Body::BirdMedium(_) => {
|
||||
self.bird_medium_states
|
||||
.get_mut(&entity)
|
||||
@ -374,6 +394,10 @@ impl FigureMgr {
|
||||
.quadruped_medium_states
|
||||
.get(&entity)
|
||||
.map(|state| state.lpindex),
|
||||
Body::QuadrupedLow(_) => self
|
||||
.quadruped_low_states
|
||||
.get(&entity)
|
||||
.map(|state| state.lpindex),
|
||||
Body::BirdMedium(_) => self
|
||||
.bird_medium_states
|
||||
.get(&entity)
|
||||
@ -430,6 +454,12 @@ impl FigureMgr {
|
||||
state.visible = false
|
||||
});
|
||||
},
|
||||
Body::QuadrupedLow(_) => {
|
||||
self.quadruped_low_states.get_mut(&entity).map(|state| {
|
||||
state.lpindex = lpindex;
|
||||
state.visible = false
|
||||
});
|
||||
},
|
||||
Body::BirdMedium(_) => {
|
||||
self.bird_medium_states.get_mut(&entity).map(|state| {
|
||||
state.lpindex = lpindex;
|
||||
@ -989,6 +1019,89 @@ impl FigureMgr {
|
||||
is_player,
|
||||
);
|
||||
},
|
||||
Body::QuadrupedLow(_) => {
|
||||
let skeleton_attr = &self
|
||||
.quadruped_low_model_cache
|
||||
.get_or_create_model(
|
||||
renderer,
|
||||
*body,
|
||||
loadout,
|
||||
tick,
|
||||
CameraMode::default(),
|
||||
None,
|
||||
)
|
||||
.1;
|
||||
|
||||
let state = self
|
||||
.quadruped_low_states
|
||||
.entry(entity)
|
||||
.or_insert_with(|| {
|
||||
FigureState::new(renderer, QuadrupedLowSkeleton::new())
|
||||
});
|
||||
|
||||
let (character, last_character) = match (character, last_character) {
|
||||
(Some(c), Some(l)) => (c, l),
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
if !character.same_variant(&last_character.0) {
|
||||
state.state_time = 0.0;
|
||||
}
|
||||
|
||||
let target_base = match (
|
||||
physics.on_ground,
|
||||
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||
physics.in_fluid, // In water
|
||||
) {
|
||||
// Standing
|
||||
(true, false, false) => {
|
||||
anim::quadruped_low::IdleAnimation::update_skeleton(
|
||||
&QuadrupedLowSkeleton::new(),
|
||||
time,
|
||||
state.state_time,
|
||||
&mut state_animation_rate,
|
||||
skeleton_attr,
|
||||
)
|
||||
},
|
||||
// Running
|
||||
(true, true, false) => {
|
||||
anim::quadruped_low::RunAnimation::update_skeleton(
|
||||
&QuadrupedLowSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.state_time,
|
||||
&mut state_animation_rate,
|
||||
skeleton_attr,
|
||||
)
|
||||
},
|
||||
// In air
|
||||
(false, _, false) => {
|
||||
anim::quadruped_low::JumpAnimation::update_skeleton(
|
||||
&QuadrupedLowSkeleton::new(),
|
||||
(vel.0.magnitude(), time),
|
||||
state.state_time,
|
||||
&mut state_animation_rate,
|
||||
skeleton_attr,
|
||||
)
|
||||
},
|
||||
|
||||
// TODO!
|
||||
_ => state.skeleton_mut().clone(),
|
||||
};
|
||||
|
||||
state.skeleton.interpolate(&target_base, dt);
|
||||
state.update(
|
||||
renderer,
|
||||
pos.0,
|
||||
ori,
|
||||
scale,
|
||||
col,
|
||||
dt,
|
||||
state_animation_rate,
|
||||
lpindex,
|
||||
true,
|
||||
is_player,
|
||||
);
|
||||
},
|
||||
Body::BirdMedium(_) => {
|
||||
let skeleton_attr = &self
|
||||
.bird_medium_model_cache
|
||||
@ -1622,6 +1735,8 @@ impl FigureMgr {
|
||||
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
||||
self.quadruped_medium_states
|
||||
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
||||
self.quadruped_low_states
|
||||
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
||||
self.bird_medium_states
|
||||
.retain(|entity, _| ecs.entities().is_alive(*entity));
|
||||
self.fish_medium_states
|
||||
@ -1774,6 +1889,7 @@ impl FigureMgr {
|
||||
critter_model_cache,
|
||||
quadruped_small_model_cache,
|
||||
quadruped_medium_model_cache,
|
||||
quadruped_low_model_cache,
|
||||
bird_medium_model_cache,
|
||||
bird_small_model_cache,
|
||||
dragon_model_cache,
|
||||
@ -1784,6 +1900,7 @@ impl FigureMgr {
|
||||
character_states,
|
||||
quadruped_small_states,
|
||||
quadruped_medium_states,
|
||||
quadruped_low_states,
|
||||
bird_medium_states,
|
||||
fish_medium_states,
|
||||
critter_states,
|
||||
@ -1846,6 +1963,22 @@ impl FigureMgr {
|
||||
.0,
|
||||
)
|
||||
}),
|
||||
Body::QuadrupedLow(_) => quadruped_low_states.get(&entity).map(|state| {
|
||||
(
|
||||
state.locals(),
|
||||
state.bone_consts(),
|
||||
&quadruped_low_model_cache
|
||||
.get_or_create_model(
|
||||
renderer,
|
||||
*body,
|
||||
loadout,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
character_state,
|
||||
)
|
||||
.0,
|
||||
)
|
||||
}),
|
||||
Body::BirdMedium(_) => bird_medium_states.get(&entity).map(|state| {
|
||||
(
|
||||
state.locals(),
|
||||
@ -2022,6 +2155,7 @@ impl FigureMgr {
|
||||
+ self.quadruped_small_states.len()
|
||||
+ self.character_states.len()
|
||||
+ self.quadruped_medium_states.len()
|
||||
+ self.quadruped_low_states.len()
|
||||
+ self.bird_medium_states.len()
|
||||
+ self.fish_medium_states.len()
|
||||
+ self.critter_states.len()
|
||||
@ -2048,6 +2182,11 @@ impl FigureMgr {
|
||||
.iter()
|
||||
.filter(|(_, c)| c.visible)
|
||||
.count()
|
||||
+ self
|
||||
.quadruped_low_states
|
||||
.iter()
|
||||
.filter(|(_, c)| c.visible)
|
||||
.count()
|
||||
+ self
|
||||
.bird_medium_states
|
||||
.iter()
|
||||
|
Loading…
Reference in New Issue
Block a user