biped_small setup

This commit is contained in:
jshipsey 2020-12-23 01:24:44 -05:00
parent a99a78abdb
commit 266986626d
15 changed files with 778 additions and 10 deletions

View File

@ -881,6 +881,20 @@
), ),
species: () species: ()
), ),
biped_small: (
body: (
keyword: "biped_small",
names: [
"Harvey"
]
),
species: (
clownfish: (
keyword: "gremlin",
generic: "Gremlin"
)
)
),
fish_small: ( fish_small: (
body: ( body: (
keyword: "fish_small", keyword: "fish_small",

View File

@ -0,0 +1,46 @@
({
(Gremlin, Male): (
head: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.gremlin.male.chest"),
),
chest: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.gremlin.male.chest"),
),
shorts: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.gremlin.male.chest"),
),
tail: (
offset: (-0.5, -5.0, -2.5),
central: ("npc.gremlin.male.tail"),
),
main: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.gremlin.male.chest"),
),
),
(Gremlin, Female): (
head: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.gremlin.male.chest"),
),
chest: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.gremlin.male.chest"),
),
shorts: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.gremlin.male.chest"),
),
tail: (
offset: (-0.5, -5.0, -2.5),
central: ("npc.gremlin.male.tail"),
),
main: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.gremlin.male.chest"),
),
),
})

View File

@ -0,0 +1,38 @@
({
(Gremlin, Male): (
hand_l: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.gremlin.male.hand_l"),
),
hand_r: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.gremlin.male.hand_r"),
),
foot_l: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.gremlin.male.fooot_l"),
),
foot_r: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.gremlin.male.foot_r"),
),
),
(Gremlin, Female): (
hand_l: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.gremlin.male.hand_l"),
),
hand_r: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.gremlin.male.hand_r"),
),
foot_l: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.gremlin.male.fooot_l"),
),
foot_r: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.gremlin.male.foot_r"),
),
),
})

View File

@ -150,6 +150,7 @@ impl<'a> From<&'a Body> for Psyche {
quadruped_low::Species::Pangolin => 0.4, quadruped_low::Species::Pangolin => 0.4,
_ => 0.6, _ => 0.6,
}, },
Body::BipedSmall(_) => 0.5,
Body::BirdMedium(_) => 0.5, Body::BirdMedium(_) => 0.5,
Body::BirdSmall(_) => 0.4, Body::BirdSmall(_) => 0.4,
Body::FishMedium(_) => 0.15, Body::FishMedium(_) => 0.15,

View File

@ -1,4 +1,5 @@
pub mod biped_large; pub mod biped_large;
pub mod biped_small;
pub mod bird_medium; pub mod bird_medium;
pub mod bird_small; pub mod bird_small;
pub mod dragon; pub mod dragon;
@ -38,10 +39,11 @@ make_case_elim!(
BirdSmall(body: bird_small::Body) = 6, BirdSmall(body: bird_small::Body) = 6,
FishSmall(body: fish_small::Body) = 7, FishSmall(body: fish_small::Body) = 7,
BipedLarge(body: biped_large::Body)= 8, BipedLarge(body: biped_large::Body)= 8,
Object(body: object::Body) = 9, BipedSmall(body: biped_small::Body)= 9,
Golem(body: golem::Body) = 10, Object(body: object::Body) = 10,
Theropod(body: theropod::Body) = 11, Golem(body: golem::Body) = 11,
QuadrupedLow(body: quadruped_low::Body) = 12, Theropod(body: theropod::Body) = 12,
QuadrupedLow(body: quadruped_low::Body) = 13,
} }
); );
@ -71,6 +73,7 @@ pub struct AllBodies<BodyMeta, SpeciesMeta> {
pub bird_small: BodyData<BodyMeta, ()>, pub bird_small: BodyData<BodyMeta, ()>,
pub fish_small: BodyData<BodyMeta, fish_small::AllSpecies<SpeciesMeta>>, pub fish_small: BodyData<BodyMeta, fish_small::AllSpecies<SpeciesMeta>>,
pub biped_large: BodyData<BodyMeta, biped_large::AllSpecies<SpeciesMeta>>, pub biped_large: BodyData<BodyMeta, biped_large::AllSpecies<SpeciesMeta>>,
pub biped_small: BodyData<BodyMeta, biped_small::AllSpecies<SpeciesMeta>>,
pub object: BodyData<BodyMeta, ()>, pub object: BodyData<BodyMeta, ()>,
pub golem: BodyData<BodyMeta, golem::AllSpecies<SpeciesMeta>>, pub golem: BodyData<BodyMeta, golem::AllSpecies<SpeciesMeta>>,
pub theropod: BodyData<BodyMeta, theropod::AllSpecies<SpeciesMeta>>, pub theropod: BodyData<BodyMeta, theropod::AllSpecies<SpeciesMeta>>,
@ -91,6 +94,7 @@ impl<BodyMeta, SpeciesMeta> core::ops::Index<NpcKind> for AllBodies<BodyMeta, Sp
NpcKind::Marlin => &self.fish_medium.body, NpcKind::Marlin => &self.fish_medium.body,
NpcKind::Clownfish => &self.fish_small.body, NpcKind::Clownfish => &self.fish_small.body,
NpcKind::Ogre => &self.biped_large.body, NpcKind::Ogre => &self.biped_large.body,
NpcKind::Gremlin => &self.biped_small.body,
NpcKind::StoneGolem => &self.golem.body, NpcKind::StoneGolem => &self.golem.body,
NpcKind::Archaeos => &self.theropod.body, NpcKind::Archaeos => &self.theropod.body,
NpcKind::Reddragon => &self.dragon.body, NpcKind::Reddragon => &self.dragon.body,
@ -115,6 +119,7 @@ impl<'a, BodyMeta, SpeciesMeta> core::ops::Index<&'a Body> for AllBodies<BodyMet
Body::BirdSmall(_) => &self.bird_small.body, Body::BirdSmall(_) => &self.bird_small.body,
Body::FishSmall(_) => &self.fish_small.body, Body::FishSmall(_) => &self.fish_small.body,
Body::BipedLarge(_) => &self.biped_large.body, Body::BipedLarge(_) => &self.biped_large.body,
Body::BipedSmall(_) => &self.biped_small.body,
Body::Object(_) => &self.object.body, Body::Object(_) => &self.object.body,
Body::Golem(_) => &self.golem.body, Body::Golem(_) => &self.golem.body,
Body::Theropod(_) => &self.theropod.body, Body::Theropod(_) => &self.theropod.body,
@ -200,6 +205,7 @@ impl Body {
_ => 4.6, _ => 4.6,
}, },
Body::Golem(_) => 2.5, Body::Golem(_) => 2.5,
Body::BipedSmall(_) => 0.75,
Body::Object(_) => 0.4, Body::Object(_) => 0.4,
} }
} }
@ -262,6 +268,7 @@ impl Body {
_ => 4.6, _ => 4.6,
}, },
Body::Golem(_) => 5.0, Body::Golem(_) => 5.0,
Body::BipedSmall(_) => 1.5,
Body::Object(object) => match object { Body::Object(object) => match object {
object::Body::Crossbow => 1.7, object::Body::Crossbow => 1.7,
_ => 1.0, _ => 1.0,
@ -339,6 +346,7 @@ impl Body {
biped_large::Species::Mindflayer => 8000, biped_large::Species::Mindflayer => 8000,
_ => 1000, _ => 1000,
}, },
Body::BipedSmall(_) => 10000,
Body::Object(object) => match object { Body::Object(object) => match object {
object::Body::TrainingDummy => 10000, object::Body::TrainingDummy => 10000,
object::Body::Crossbow => 800, object::Body::Crossbow => 800,
@ -428,6 +436,7 @@ impl Body {
biped_large::Species::Mindflayer => 250, biped_large::Species::Mindflayer => 250,
_ => 100, _ => 100,
}, },
Body::BipedSmall(_) => 10,
Body::Object(_) => 10, Body::Object(_) => 10,
Body::Golem(_) => 260, Body::Golem(_) => 260,
Body::Theropod(_) => 20, Body::Theropod(_) => 20,

View File

@ -0,0 +1,78 @@
use crate::{make_case_elim, make_proj_elim};
use rand::{seq::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
make_proj_elim!(
body,
#[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::BipedSmall(body) }
}
make_case_elim!(
species,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Species {
Gremlin = 0,
}
);
/// Data representing per-species generic data.
///
/// NOTE: Deliberately don't (yet?) implement serialize.
#[derive(Clone, Debug, Deserialize)]
pub struct AllSpecies<SpeciesMeta> {
pub gremlin: 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::Gremlin => &self.gremlin,
}
}
}
pub const ALL_SPECIES: [Species; 1] = [Species::Gremlin];
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() }
}
make_case_elim!(
body_type,
#[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];

View File

@ -46,7 +46,7 @@ pub use self::{
aura::{Aura, AuraChange, AuraKind, Auras}, aura::{Aura, AuraChange, AuraKind, Auras},
beam::{Beam, BeamSegment}, beam::{Beam, BeamSegment},
body::{ body::{
biped_large, bird_medium, bird_small, dragon, fish_medium, fish_small, golem, humanoid, biped_large, biped_small, bird_medium, bird_small, dragon, fish_medium, fish_small, golem, humanoid,
object, quadruped_low, quadruped_medium, quadruped_small, theropod, AllBodies, Body, object, quadruped_low, quadruped_medium, quadruped_small, theropod, AllBodies, Body,
BodyData, BodyData,
}, },

View File

@ -16,13 +16,14 @@ pub enum NpcKind {
Clownfish, Clownfish,
Marlin, Marlin,
Ogre, Ogre,
Gremlin,
Archaeos, Archaeos,
StoneGolem, StoneGolem,
Reddragon, Reddragon,
Crocodile, Crocodile,
} }
pub const ALL_NPCS: [NpcKind; 11] = [ pub const ALL_NPCS: [NpcKind; 12] = [
NpcKind::Humanoid, NpcKind::Humanoid,
NpcKind::Wolf, NpcKind::Wolf,
NpcKind::Pig, NpcKind::Pig,
@ -30,6 +31,7 @@ pub const ALL_NPCS: [NpcKind; 11] = [
NpcKind::Clownfish, NpcKind::Clownfish,
NpcKind::Marlin, NpcKind::Marlin,
NpcKind::Ogre, NpcKind::Ogre,
NpcKind::Gremlin,
NpcKind::Archaeos, NpcKind::Archaeos,
NpcKind::StoneGolem, NpcKind::StoneGolem,
NpcKind::Reddragon, NpcKind::Reddragon,
@ -123,6 +125,7 @@ pub fn kind_to_body(kind: NpcKind) -> Body {
NpcKind::Clownfish => comp::fish_small::Body::random().into(), NpcKind::Clownfish => comp::fish_small::Body::random().into(),
NpcKind::Marlin => comp::fish_medium::Body::random().into(), NpcKind::Marlin => comp::fish_medium::Body::random().into(),
NpcKind::Ogre => comp::biped_large::Body::random().into(), NpcKind::Ogre => comp::biped_large::Body::random().into(),
NpcKind::Gremlin => comp::biped_small::Body::random().into(),
NpcKind::Archaeos => comp::theropod::Body::random().into(), NpcKind::Archaeos => comp::theropod::Body::random().into(),
NpcKind::StoneGolem => comp::golem::Body::random().into(), NpcKind::StoneGolem => comp::golem::Body::random().into(),
NpcKind::Reddragon => comp::dragon::Body::random().into(), NpcKind::Reddragon => comp::dragon::Body::random().into(),
@ -249,6 +252,14 @@ impl NpcBody {
comp::biped_large::Body::random_with, comp::biped_large::Body::random_with,
) )
}) })
.or_else(|| {
parse(
s,
NpcKind::Gremlin,
&npc_names.biped_small,
comp::biped_small::Body::random_with,
)
})
.or_else(|| { .or_else(|| {
parse( parse(
s, s,

View File

@ -60,6 +60,7 @@ impl Body {
quadruped_medium::Species::Kelpie => 180.0, quadruped_medium::Species::Kelpie => 180.0,
quadruped_medium::Species::Horse => 180.0, quadruped_medium::Species::Horse => 180.0,
}, },
Body::BipedSmall(_) => 100.0,
Body::BirdMedium(_) => 80.0, Body::BirdMedium(_) => 80.0,
Body::FishMedium(_) => 80.0, Body::FishMedium(_) => 80.0,
Body::Dragon(_) => 250.0, Body::Dragon(_) => 250.0,
@ -116,6 +117,7 @@ impl Body {
Body::BirdSmall(_) => 35.0, Body::BirdSmall(_) => 35.0,
Body::FishSmall(_) => 10.0, Body::FishSmall(_) => 10.0,
Body::BipedLarge(_) => 12.0, Body::BipedLarge(_) => 12.0,
Body::BipedSmall(_) => 12.0,
Body::Object(_) => 10.0, Body::Object(_) => 10.0,
Body::Golem(_) => 8.0, Body::Golem(_) => 8.0,
Body::Theropod(theropod) => match theropod.species { Body::Theropod(theropod) => match theropod.species {

View File

@ -0,0 +1,44 @@
use super::{
super::{vek::*, Animation},
BipedSmallSkeleton, SkeletonAttr,
};
pub struct IdleAnimation;
type IdleAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>);
impl Animation for IdleAnimation {
type Dependency = IdleAnimationDependency;
type Skeleton = BipedSmallSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"biped_small_idle\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "Biped_small_idle")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency,
anim_time: f64,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.head.scale = Vec3::one();
next.chest.scale = Vec3::one() / 13.0;
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0;
next.shorts.position = Vec3::new(0.0, s_a.shorts.0, s_a.shorts.1);
next.main.position = Vec3::new(0.0, 0.0, 0.0);
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
next.hand_l.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2);
next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2);
next.foot_l.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next
}
}

View File

@ -0,0 +1,114 @@
pub mod idle;
pub mod run;
// Reexports
pub use self::{idle::IdleAnimation, run::RunAnimation};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::biped_small::Body;
skeleton_impls!(struct BipedSmallSkeleton {
+ head,
+ chest,
+ shorts,
+ tail,
+ main,
+ hand_l,
+ hand_r,
+ foot_l,
+ foot_r,
});
impl Skeleton for BipedSmallSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 9;
#[cfg(feature = "use-dyn-lib")]
const COMPUTE_FN: &'static [u8] = b"biped_small_compute_mats\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "biped_small_compute_mats")]
fn compute_matrices_inner(
&self,
base_mat: Mat4<f32>,
buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
) -> Vec3<f32> {
let chest_mat = base_mat * Mat4::<f32>::from(self.chest);
let shorts_mat = chest_mat * Mat4::<f32>::from(self.chest);
*(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
make_bone(chest_mat * Mat4::<f32>::from(self.head)),
make_bone(chest_mat),
make_bone(shorts_mat),
make_bone(shorts_mat * Mat4::<f32>::from(self.tail)),
make_bone(chest_mat * Mat4::<f32>::from(self.main)),
make_bone(chest_mat * Mat4::<f32>::from(self.hand_l)),
make_bone(chest_mat * Mat4::<f32>::from(self.hand_l)),
make_bone(base_mat * Mat4::<f32>::from(self.foot_l)),
make_bone(base_mat * Mat4::<f32>::from(self.foot_l)),
];
Vec3::default()
}
}
pub struct SkeletonAttr {
head: (f32, f32),
chest: (f32, f32),
shorts: (f32, f32),
tail: (f32, f32),
hand: (f32, f32, f32),
foot: (f32, f32, 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::BipedSmall(body) => Ok(SkeletonAttr::from(body)),
_ => Err(()),
}
}
}
impl Default for SkeletonAttr {
fn default() -> Self {
Self {
head: (0.0, 0.0),
chest: (0.0, 0.0),
shorts: (0.0, 0.0),
tail: (0.0, 0.0),
hand: (0.0, 0.0, 0.0),
foot: (0.0, 0.0, 0.0),
}
}
}
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::biped_small::Species::*;
Self {
head: match (body.species, body.body_type) {
(Gremlin, _) => (0.0, 5.0),
},
chest: match (body.species, body.body_type) {
(Gremlin, _) => (0.0, 5.0),
},
shorts: match (body.species, body.body_type) {
(Gremlin, _) => (0.0, 5.0),
},
tail: match (body.species, body.body_type) {
(Gremlin, _) => (-7.5, -0.5),
},
hand: match (body.species, body.body_type) {
(Gremlin, _) => (2.0, 0.5, 1.0),
},
foot: match (body.species, body.body_type) {
(Gremlin, _) => (2.0, 0.5, 1.0),
},
}
}
}

View File

@ -0,0 +1,44 @@
use super::{
super::{vek::*, Animation},
BipedSmallSkeleton, SkeletonAttr,
};
pub struct RunAnimation;
type RunAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>);
impl Animation for RunAnimation {
type Dependency = RunAnimationDependency;
type Skeleton = BipedSmallSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"biped_small_run\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "Biped_small_run")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency,
anim_time: f64,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.head.scale = Vec3::one();
next.chest.scale = Vec3::one() / 13.0;
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1) / 13.0;
next.shorts.position = Vec3::new(0.0, s_a.shorts.0, s_a.shorts.1);
next.main.position = Vec3::new(0.0, 0.0, 0.0);
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
next.hand_l.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2);
next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1, s_a.hand.2);
next.foot_l.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next.foot_r.position = Vec3::new(s_a.foot.0, s_a.foot.1, s_a.foot.2);
next
}
}

View File

@ -40,6 +40,7 @@ macro_rules! skeleton_impls {
} }
pub mod biped_large; pub mod biped_large;
pub mod biped_small;
pub mod bird_medium; pub mod bird_medium;
pub mod bird_small; pub mod bird_small;
pub mod character; pub mod character;

View File

@ -3,6 +3,7 @@ use common::{
assets::{self, AssetExt, AssetHandle, DotVoxAsset, Ron}, assets::{self, AssetExt, AssetHandle, DotVoxAsset, Ron},
comp::{ comp::{
biped_large::{self, BodyType as BLBodyType, Species as BLSpecies}, biped_large::{self, BodyType as BLBodyType, Species as BLSpecies},
biped_small::{self, BodyType as BSBodyType, Species as BSSpecies},
bird_medium::{self, BodyType as BMBodyType, Species as BMSpecies}, bird_medium::{self, BodyType as BMBodyType, Species as BMSpecies},
bird_small, bird_small,
dragon::{self, BodyType as DBodyType, Species as DSpecies}, dragon::{self, BodyType as DBodyType, Species as DSpecies},
@ -2468,6 +2469,241 @@ impl FishSmallLateralSpec {
//// ////
#[derive(Deserialize)]
struct BipedSmallCentralSpec(HashMap<(BSSpecies, BSBodyType), SidedBSCentralVoxSpec>);
#[derive(Deserialize)]
struct SidedBSCentralVoxSpec {
head: BipedSmallCentralSubSpec,
chest: BipedSmallCentralSubSpec,
shorts: BipedSmallCentralSubSpec,
tail: BipedSmallCentralSubSpec,
main: BipedSmallCentralSubSpec,
}
#[derive(Deserialize)]
struct BipedSmallCentralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
central: VoxSimple,
}
#[derive(Deserialize)]
struct BipedSmallLateralSpec(HashMap<(BSSpecies, BSBodyType), SidedBSLateralVoxSpec>);
#[derive(Deserialize)]
struct SidedBSLateralVoxSpec {
hand_l: BipedSmallLateralSubSpec,
hand_r: BipedSmallLateralSubSpec,
foot_l: BipedSmallLateralSubSpec,
foot_r: BipedSmallLateralSubSpec,
}
#[derive(Deserialize)]
struct BipedSmallLateralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
lateral: VoxSimple,
}
make_vox_spec!(
biped_small::Body,
struct BipedSmallSpec {
central: BipedSmallCentralSpec = "voxygen.voxel.biped_small_central_manifest",
lateral: BipedSmallLateralSpec = "voxygen.voxel.biped_small_lateral_manifest",
},
|FigureKey { body, .. }, spec| {
[
Some(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.central.read().0.mesh_shorts(
body.species,
body.body_type,
)),
Some(spec.central.read().0.mesh_tail(
body.species,
body.body_type,
)),
Some(spec.central.read().0.mesh_main(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_hand_l(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_hand_r(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_foot_l(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_foot_r(
body.species,
body.body_type,
)),
None,
None,
None,
None,
None,
None,
None,
]
},
);
impl BipedSmallCentralSpec {
fn mesh_head(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No head specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.head.central.0);
(central, Vec3::from(spec.head.offset))
}
fn mesh_chest(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No chest specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.chest.central.0);
(central, Vec3::from(spec.chest.offset))
}
fn mesh_shorts(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No shorts specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.shorts.central.0);
(central, Vec3::from(spec.shorts.offset))
}
fn mesh_tail(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes {
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));
},
};
let central = graceful_load_segment(&spec.tail.central.0);
(central, Vec3::from(spec.tail.offset))
}
fn mesh_main(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No main specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.main.central.0);
(central, Vec3::from(spec.main.offset))
}
}
impl BipedSmallLateralSpec {
fn mesh_hand_l(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No hand specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment(&spec.hand_l.lateral.0);
(lateral, Vec3::from(spec.hand_l.offset))
}
fn mesh_hand_r(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No hand specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let lateral = graceful_load_segment(&spec.hand_r.lateral.0);
(lateral, Vec3::from(spec.hand_r.offset))
}
fn mesh_foot_l(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes {
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));
},
};
let lateral = graceful_load_segment(&spec.foot_l.lateral.0);
(lateral, Vec3::from(spec.foot_l.offset))
}
fn mesh_foot_r(&self, species: BSSpecies, body_type: BSBodyType) -> BoneMeshes {
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));
},
};
let lateral = graceful_load_segment(&spec.foot_r.lateral.0);
(lateral, Vec3::from(spec.foot_r.offset))
}
}
////
#[derive(Deserialize)] #[derive(Deserialize)]
struct DragonCentralSpec(HashMap<(DSpecies, DBodyType), SidedDCentralVoxSpec>); struct DragonCentralSpec(HashMap<(DSpecies, DBodyType), SidedDCentralVoxSpec>);

View File

@ -18,10 +18,10 @@ use crate::{
}, },
}; };
use anim::{ use anim::{
biped_large::BipedLargeSkeleton, bird_medium::BirdMediumSkeleton, biped_large::BipedLargeSkeleton, biped_small::BipedSmallSkeleton,
bird_small::BirdSmallSkeleton, character::CharacterSkeleton, dragon::DragonSkeleton, bird_medium::BirdMediumSkeleton, bird_small::BirdSmallSkeleton, character::CharacterSkeleton,
fish_medium::FishMediumSkeleton, fish_small::FishSmallSkeleton, golem::GolemSkeleton, dragon::DragonSkeleton, fish_medium::FishMediumSkeleton, fish_small::FishSmallSkeleton,
object::ObjectSkeleton, quadruped_low::QuadrupedLowSkeleton, golem::GolemSkeleton, object::ObjectSkeleton, quadruped_low::QuadrupedLowSkeleton,
quadruped_medium::QuadrupedMediumSkeleton, quadruped_small::QuadrupedSmallSkeleton, quadruped_medium::QuadrupedMediumSkeleton, quadruped_small::QuadrupedSmallSkeleton,
theropod::TheropodSkeleton, Animation, Skeleton, theropod::TheropodSkeleton, Animation, Skeleton,
}; };
@ -98,6 +98,7 @@ struct FigureMgrStates {
bird_small_states: HashMap<EcsEntity, FigureState<BirdSmallSkeleton>>, bird_small_states: HashMap<EcsEntity, FigureState<BirdSmallSkeleton>>,
fish_small_states: HashMap<EcsEntity, FigureState<FishSmallSkeleton>>, fish_small_states: HashMap<EcsEntity, FigureState<FishSmallSkeleton>>,
biped_large_states: HashMap<EcsEntity, FigureState<BipedLargeSkeleton>>, biped_large_states: HashMap<EcsEntity, FigureState<BipedLargeSkeleton>>,
biped_small_states: HashMap<EcsEntity, FigureState<BipedSmallSkeleton>>,
golem_states: HashMap<EcsEntity, FigureState<GolemSkeleton>>, golem_states: HashMap<EcsEntity, FigureState<GolemSkeleton>>,
object_states: HashMap<EcsEntity, FigureState<ObjectSkeleton>>, object_states: HashMap<EcsEntity, FigureState<ObjectSkeleton>>,
} }
@ -116,6 +117,7 @@ impl FigureMgrStates {
bird_small_states: HashMap::new(), bird_small_states: HashMap::new(),
fish_small_states: HashMap::new(), fish_small_states: HashMap::new(),
biped_large_states: HashMap::new(), biped_large_states: HashMap::new(),
biped_small_states: HashMap::new(),
golem_states: HashMap::new(), golem_states: HashMap::new(),
object_states: HashMap::new(), object_states: HashMap::new(),
} }
@ -172,6 +174,10 @@ impl FigureMgrStates {
.biped_large_states .biped_large_states
.get_mut(&entity) .get_mut(&entity)
.map(DerefMut::deref_mut), .map(DerefMut::deref_mut),
Body::BipedSmall(_) => self
.biped_small_states
.get_mut(&entity)
.map(DerefMut::deref_mut),
Body::Golem(_) => self.golem_states.get_mut(&entity).map(DerefMut::deref_mut), Body::Golem(_) => self.golem_states.get_mut(&entity).map(DerefMut::deref_mut),
Body::Object(_) => self.object_states.get_mut(&entity).map(DerefMut::deref_mut), Body::Object(_) => self.object_states.get_mut(&entity).map(DerefMut::deref_mut),
} }
@ -196,6 +202,7 @@ impl FigureMgrStates {
Body::BirdSmall(_) => self.bird_small_states.remove(&entity).map(|e| e.meta), Body::BirdSmall(_) => self.bird_small_states.remove(&entity).map(|e| e.meta),
Body::FishSmall(_) => self.fish_small_states.remove(&entity).map(|e| e.meta), Body::FishSmall(_) => self.fish_small_states.remove(&entity).map(|e| e.meta),
Body::BipedLarge(_) => self.biped_large_states.remove(&entity).map(|e| e.meta), Body::BipedLarge(_) => self.biped_large_states.remove(&entity).map(|e| e.meta),
Body::BipedSmall(_) => self.biped_small_states.remove(&entity).map(|e| e.meta),
Body::Golem(_) => self.golem_states.remove(&entity).map(|e| e.meta), Body::Golem(_) => self.golem_states.remove(&entity).map(|e| e.meta),
Body::Object(_) => self.object_states.remove(&entity).map(|e| e.meta), Body::Object(_) => self.object_states.remove(&entity).map(|e| e.meta),
} }
@ -214,6 +221,7 @@ impl FigureMgrStates {
self.bird_small_states.retain(|k, v| f(k, &mut *v)); self.bird_small_states.retain(|k, v| f(k, &mut *v));
self.fish_small_states.retain(|k, v| f(k, &mut *v)); self.fish_small_states.retain(|k, v| f(k, &mut *v));
self.biped_large_states.retain(|k, v| f(k, &mut *v)); self.biped_large_states.retain(|k, v| f(k, &mut *v));
self.biped_small_states.retain(|k, v| f(k, &mut *v));
self.golem_states.retain(|k, v| f(k, &mut *v)); self.golem_states.retain(|k, v| f(k, &mut *v));
self.object_states.retain(|k, v| f(k, &mut *v)); self.object_states.retain(|k, v| f(k, &mut *v));
} }
@ -231,6 +239,7 @@ impl FigureMgrStates {
+ self.bird_small_states.len() + self.bird_small_states.len()
+ self.fish_small_states.len() + self.fish_small_states.len()
+ self.biped_large_states.len() + self.biped_large_states.len()
+ self.biped_small_states.len()
+ self.golem_states.len() + self.golem_states.len()
+ self.object_states.len() + self.object_states.len()
} }
@ -290,6 +299,11 @@ impl FigureMgrStates {
.iter() .iter()
.filter(|(_, c)| c.visible()) .filter(|(_, c)| c.visible())
.count() .count()
+ self
.biped_small_states
.iter()
.filter(|(_, c)| c.visible())
.count()
+ self + self
.golem_states .golem_states
.iter() .iter()
@ -316,6 +330,7 @@ pub struct FigureMgr {
fish_medium_model_cache: FigureModelCache<FishMediumSkeleton>, fish_medium_model_cache: FigureModelCache<FishMediumSkeleton>,
fish_small_model_cache: FigureModelCache<FishSmallSkeleton>, fish_small_model_cache: FigureModelCache<FishSmallSkeleton>,
biped_large_model_cache: FigureModelCache<BipedLargeSkeleton>, biped_large_model_cache: FigureModelCache<BipedLargeSkeleton>,
biped_small_model_cache: FigureModelCache<BipedSmallSkeleton>,
object_model_cache: FigureModelCache<ObjectSkeleton>, object_model_cache: FigureModelCache<ObjectSkeleton>,
golem_model_cache: FigureModelCache<GolemSkeleton>, golem_model_cache: FigureModelCache<GolemSkeleton>,
states: FigureMgrStates, states: FigureMgrStates,
@ -336,6 +351,7 @@ impl FigureMgr {
fish_medium_model_cache: FigureModelCache::new(), fish_medium_model_cache: FigureModelCache::new(),
fish_small_model_cache: FigureModelCache::new(), fish_small_model_cache: FigureModelCache::new(),
biped_large_model_cache: FigureModelCache::new(), biped_large_model_cache: FigureModelCache::new(),
biped_small_model_cache: FigureModelCache::new(),
object_model_cache: FigureModelCache::new(), object_model_cache: FigureModelCache::new(),
golem_model_cache: FigureModelCache::new(), golem_model_cache: FigureModelCache::new(),
states: FigureMgrStates::default(), states: FigureMgrStates::default(),
@ -365,6 +381,8 @@ impl FigureMgr {
.clean(&mut self.col_lights, tick); .clean(&mut self.col_lights, tick);
self.biped_large_model_cache self.biped_large_model_cache
.clean(&mut self.col_lights, tick); .clean(&mut self.col_lights, tick);
self.biped_small_model_cache
.clean(&mut self.col_lights, tick);
self.object_model_cache.clean(&mut self.col_lights, tick); self.object_model_cache.clean(&mut self.col_lights, tick);
self.golem_model_cache.clean(&mut self.col_lights, tick); self.golem_model_cache.clean(&mut self.col_lights, tick);
} }
@ -2519,6 +2537,99 @@ impl FigureMgr {
terrain, terrain,
); );
}, },
Body::BipedSmall(body) => {
let (model, skeleton_attr) = self.biped_small_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
*body,
inventory,
tick,
player_camera_mode,
player_character_state,
scene_data.thread_pool,
);
let state = self
.states
.biped_small_states
.entry(entity)
.or_insert_with(|| {
FigureState::new(renderer, BipedSmallSkeleton::default())
});
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_liquid.is_some(), // In water
) {
// Idle
(true, false, false) => anim::biped_small::IdleAnimation::update_skeleton(
&BipedSmallSkeleton::default(),
(vel.0, ori, state.last_ori, time, state.avg_vel),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// Run
(true, true, _) => anim::biped_small::RunAnimation::update_skeleton(
&BipedSmallSkeleton::default(),
(vel.0, ori, state.last_ori, time, state.avg_vel),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// Jump
(false, _, false) => anim::biped_small::RunAnimation::update_skeleton(
&BipedSmallSkeleton::default(),
(vel.0, ori, state.last_ori, time, state.avg_vel),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// Swim
(false, _, true) => anim::biped_small::RunAnimation::update_skeleton(
&BipedSmallSkeleton::default(),
(vel.0, ori, state.last_ori, time, state.avg_vel),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
_ => anim::biped_small::RunAnimation::update_skeleton(
&BipedSmallSkeleton::default(),
(vel.0, ori, state.last_ori, time, state.avg_vel),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
};
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_base, dt_lerp);
state.update(
renderer,
pos.0,
ori,
scale,
col,
dt,
state_animation_rate,
model,
lpindex,
in_frustum,
is_player,
camera,
&mut update_buf,
terrain,
);
},
Body::Dragon(body) => { Body::Dragon(body) => {
let (model, skeleton_attr) = self.dragon_model_cache.get_or_create_model( let (model, skeleton_attr) = self.dragon_model_cache.get_or_create_model(
renderer, renderer,
@ -3808,6 +3919,7 @@ impl FigureMgr {
fish_medium_model_cache, fish_medium_model_cache,
fish_small_model_cache, fish_small_model_cache,
biped_large_model_cache, biped_large_model_cache,
biped_small_model_cache,
object_model_cache, object_model_cache,
golem_model_cache, golem_model_cache,
states: states:
@ -3823,6 +3935,7 @@ impl FigureMgr {
bird_small_states, bird_small_states,
fish_small_states, fish_small_states,
biped_large_states, biped_large_states,
biped_small_states,
golem_states, golem_states,
object_states, object_states,
}, },
@ -4016,6 +4129,23 @@ impl FigureMgr {
), ),
) )
}), }),
Body::BipedSmall(body) => biped_small_states
.get(&entity)
.filter(|state| filter_state(&*state))
.map(move |state| {
(
state.locals(),
state.bone_consts(),
biped_small_model_cache.get_model(
col_lights,
*body,
inventory,
tick,
player_camera_mode,
character_state,
),
)
}),
Body::Golem(body) => golem_states Body::Golem(body) => golem_states
.get(&entity) .get(&entity)
.filter(|state| filter_state(&*state)) .filter(|state| filter_state(&*state))