Merge branch 'snowram/fishes' into 'master'

Add fishes

See merge request veloren/veloren!1577
This commit is contained in:
Justin Shipsey 2020-12-09 02:59:55 +00:00
commit c42cdc685c
44 changed files with 966 additions and 484 deletions

View File

@ -686,7 +686,7 @@
"species": {
"reddragon": {
"keyword": "reddragon",
"generic": "Reddragon"
"generic": "Red Dragon"
}
}
},
@ -700,16 +700,30 @@
"fish_small": {
"body": {
"keyword": "fish_small",
"names": []
"names": [
"Dagon"
]
},
"species": null
"species": {
"clownfish": {
"keyword": "clownfish",
"generic": "Clownfish"
}
}
},
"fish_medium": {
"body": {
"keyword": "fish_medium",
"names": []
"names": [
"Njord"
]
},
"species": null
"species": {
"marlin": {
"keyword": "marlin",
"generic": "Marlin"
}
}
},
"bird_small": {
"body": {

View File

@ -0,0 +1,46 @@
({
(Marlin, Male): (
head: (
offset: (-2.5, 0.0, -3.0),
central: ("npc.marlin.male.head"),
),
jaw: (
offset: (-4.0, 0.0, -1.5),
central: ("armor.empty"),
),
chest_front: (
offset: (-2.5, -5.0, -2.5),
central: ("npc.marlin.male.chest_front"),
),
chest_back: (
offset: (-2.5, -7.0, -3.5),
central: ("npc.marlin.male.chest_back"),
),
tail: (
offset: (-0.5, -11.0, -4.5),
central: ("npc.marlin.male.tail"),
),
),
(Marlin, Female): (
head: (
offset: (-2.5, 0.0, -3.0),
central: ("npc.marlin.male.head"),
),
jaw: (
offset: (-4.0, 0.0, -1.5),
central: ("armor.empty"),
),
chest_front: (
offset: (-2.5, -5.0, -2.5),
central: ("npc.marlin.male.chest_front"),
),
chest_back: (
offset: (-2.5, -7.0, -3.5),
central: ("npc.marlin.male.chest_back"),
),
tail: (
offset: (-0.5, -11.0, -4.5),
central: ("npc.marlin.male.tail"),
),
),
})

View File

@ -0,0 +1,22 @@
({
(Marlin, Male): (
fin_l: (
offset: (-3.0, -5.0, -4.0),
lateral: ("npc.marlin.male.fin_l"),
),
fin_r: (
offset: (0.0, -5.0, -4.0),
lateral: ("npc.marlin.male.fin_r"),
),
),
(Marlin, Female): (
fin_l: (
offset: (-3.0, -5.0, -4.0),
lateral: ("npc.marlin.male.fin_l"),
),
fin_r: (
offset: (0.0, -5.0, -4.0),
lateral: ("npc.marlin.male.fin_r"),
),
),
})

View File

@ -0,0 +1,22 @@
({
(Clownfish, Male): (
chest: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.clownfish.male.chest"),
),
tail: (
offset: (-0.5, -5.0, -2.5),
central: ("npc.clownfish.male.tail"),
),
),
(Clownfish, Female): (
chest: (
offset: (-1.5, -7.5, -5.0),
central: ("npc.clownfish.male.chest"),
),
tail: (
offset: (-0.5, -5.0, -2.5),
central: ("npc.clownfish.male.tail"),
),
),
})

View File

@ -0,0 +1,22 @@
({
(Clownfish, Male): (
fin_l: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.clownfish.male.fin_l"),
),
fin_r: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.clownfish.male.fin_r"),
),
),
(Clownfish, Female): (
fin_l: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.clownfish.male.fin_l"),
),
fin_r: (
offset: (-0.5, -3.0, -4.0),
lateral: ("npc.clownfish.male.fin_r"),
),
),
})

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -812,7 +812,7 @@
(Roshwalr, Female): (
head: (
offset: (-13.0, 0.0, -12.0),
central: ("npc.roshwalr.male.head"),
central: ("npc.roshwalr.female.head"),
),
neck: (
offset: (-7.0, -2.0, -11.5),

View File

@ -65,10 +65,10 @@ pub struct AllBodies<BodyMeta, SpeciesMeta> {
pub quadruped_small: BodyData<BodyMeta, quadruped_small::AllSpecies<SpeciesMeta>>,
pub quadruped_medium: BodyData<BodyMeta, quadruped_medium::AllSpecies<SpeciesMeta>>,
pub bird_medium: BodyData<BodyMeta, bird_medium::AllSpecies<SpeciesMeta>>,
pub fish_medium: BodyData<BodyMeta, ()>,
pub fish_medium: BodyData<BodyMeta, fish_medium::AllSpecies<SpeciesMeta>>,
pub dragon: BodyData<BodyMeta, dragon::AllSpecies<SpeciesMeta>>,
pub bird_small: BodyData<BodyMeta, ()>,
pub fish_small: BodyData<BodyMeta, ()>,
pub fish_small: BodyData<BodyMeta, fish_small::AllSpecies<SpeciesMeta>>,
pub biped_large: BodyData<BodyMeta, biped_large::AllSpecies<SpeciesMeta>>,
pub object: BodyData<BodyMeta, ()>,
pub golem: BodyData<BodyMeta, golem::AllSpecies<SpeciesMeta>>,
@ -87,6 +87,8 @@ impl<BodyMeta, SpeciesMeta> core::ops::Index<NpcKind> for AllBodies<BodyMeta, Sp
NpcKind::Pig => &self.quadruped_small.body,
NpcKind::Wolf => &self.quadruped_medium.body,
NpcKind::Duck => &self.bird_medium.body,
NpcKind::Marlin => &self.fish_medium.body,
NpcKind::Clownfish => &self.fish_small.body,
NpcKind::Ogre => &self.biped_large.body,
NpcKind::StoneGolem => &self.golem.body,
NpcKind::Archaeos => &self.theropod.body,
@ -231,10 +233,10 @@ impl Body {
bird_medium::Species::Cockatrice => 1.8,
_ => 1.1,
},
Body::FishMedium(_) => 1.1,
Body::FishMedium(_) => 0.8,
Body::Dragon(_) => 16.0,
Body::BirdSmall(_) => 1.1,
Body::FishSmall(_) => 0.9,
Body::FishSmall(_) => 0.6,
Body::BipedLarge(body) => match body.species {
biped_large::Species::Slysaurok => 2.3,
biped_large::Species::Occultsaurok => 2.8,

View File

@ -6,86 +6,73 @@ make_proj_elim!(
body,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Body {
pub head: Head,
pub torso: Torso,
pub rear: Rear,
pub tail: Tail,
pub fin_l: FinL,
pub fin_r: FinR,
pub species: Species,
pub body_type: BodyType,
}
);
impl Body {
pub fn random() -> Self {
let mut rng = thread_rng();
Self {
head: *(&ALL_HEADS).choose(&mut rng).unwrap(),
torso: *(&ALL_TORSOS).choose(&mut rng).unwrap(),
rear: *(&ALL_REARS).choose(&mut rng).unwrap(),
tail: *(&ALL_TAILS).choose(&mut rng).unwrap(),
fin_l: *(&ALL_FIN_LS).choose(&mut rng).unwrap(),
fin_r: *(&ALL_FIN_RS).choose(&mut rng).unwrap(),
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::FishMedium(body) }
}
make_case_elim!(
species,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Species {
Marlin = 0,
}
);
/// Data representing per-species generic data.
///
/// NOTE: Deliberately don't (yet?) implement serialize.
#[derive(Clone, Debug, Deserialize)]
pub struct AllSpecies<SpeciesMeta> {
pub marlin: 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::Marlin => &self.marlin,
}
}
}
make_case_elim!(
head,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Head {
Default = 0,
}
);
pub const ALL_SPECIES: [Species; 1] = [Species::Marlin];
const ALL_HEADS: [Head; 1] = [Head::Default];
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!(
torso,
body_type,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Torso {
Default = 0,
pub enum BodyType {
Female = 0,
Male = 1,
}
);
const ALL_TORSOS: [Torso; 1] = [Torso::Default];
make_case_elim!(
rear,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Rear {
Default = 0,
}
);
const ALL_REARS: [Rear; 1] = [Rear::Default];
make_case_elim!(
tail,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Tail {
Default = 0,
}
);
const ALL_TAILS: [Tail; 1] = [Tail::Default];
make_case_elim!(
fin_l,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum FinL {
Default = 0,
}
);
const ALL_FIN_LS: [FinL; 1] = [FinL::Default];
make_case_elim!(
fin_r,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum FinR {
Default = 0,
}
);
const ALL_FIN_RS: [FinR; 1] = [FinR::Default];
pub const ALL_BODY_TYPES: [BodyType; 2] = [BodyType::Female, BodyType::Male];

View File

@ -6,39 +6,73 @@ make_proj_elim!(
body,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Body {
pub torso: Torso,
pub tail: Tail,
pub species: Species,
pub body_type: BodyType,
}
);
impl Body {
pub fn random() -> Self {
let mut rng = thread_rng();
Self {
torso: *(&ALL_TORSOS).choose(&mut rng).unwrap(),
tail: *(&ALL_TAILS).choose(&mut rng).unwrap(),
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::FishSmall(body) }
}
make_case_elim!(
species,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Species {
Clownfish = 0,
}
);
/// Data representing per-species generic data.
///
/// NOTE: Deliberately don't (yet?) implement serialize.
#[derive(Clone, Debug, Deserialize)]
pub struct AllSpecies<SpeciesMeta> {
pub clownfish: 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::Clownfish => &self.clownfish,
}
}
}
make_case_elim!(
torso,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Torso {
Default = 0,
}
);
pub const ALL_SPECIES: [Species; 1] = [Species::Clownfish];
const ALL_TORSOS: [Torso; 1] = [Torso::Default];
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!(
tail,
body_type,
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Tail {
Default = 0,
pub enum BodyType {
Female = 0,
Male = 1,
}
);
const ALL_TAILS: [Tail; 1] = [Tail::Default];
pub const ALL_BODY_TYPES: [BodyType; 2] = [BodyType::Female, BodyType::Male];

View File

@ -121,6 +121,8 @@ impl EntityInfo {
Some(get_npc_name(&NPC_NAMES.quadruped_medium, body.species))
},
Body::BirdMedium(body) => Some(get_npc_name(&NPC_NAMES.bird_medium, body.species)),
Body::FishSmall(body) => Some(get_npc_name(&NPC_NAMES.fish_small, body.species)),
Body::FishMedium(body) => Some(get_npc_name(&NPC_NAMES.fish_medium, body.species)),
Body::Theropod(body) => Some(get_npc_name(&NPC_NAMES.theropod, body.species)),
Body::QuadrupedSmall(body) => {
Some(get_npc_name(&NPC_NAMES.quadruped_small, body.species))

View File

@ -13,6 +13,8 @@ pub enum NpcKind {
Wolf,
Pig,
Duck,
Clownfish,
Marlin,
Ogre,
Archaeos,
StoneGolem,
@ -20,11 +22,13 @@ pub enum NpcKind {
Crocodile,
}
pub const ALL_NPCS: [NpcKind; 9] = [
pub const ALL_NPCS: [NpcKind; 11] = [
NpcKind::Humanoid,
NpcKind::Wolf,
NpcKind::Pig,
NpcKind::Duck,
NpcKind::Clownfish,
NpcKind::Marlin,
NpcKind::Ogre,
NpcKind::Archaeos,
NpcKind::StoneGolem,
@ -93,6 +97,8 @@ pub fn kind_to_body(kind: NpcKind) -> Body {
NpcKind::Pig => comp::quadruped_small::Body::random().into(),
NpcKind::Wolf => comp::quadruped_medium::Body::random().into(),
NpcKind::Duck => comp::bird_medium::Body::random().into(),
NpcKind::Clownfish => comp::fish_small::Body::random().into(),
NpcKind::Marlin => comp::fish_medium::Body::random().into(),
NpcKind::Ogre => comp::biped_large::Body::random().into(),
NpcKind::Archaeos => comp::theropod::Body::random().into(),
NpcKind::StoneGolem => comp::golem::Body::random().into(),
@ -195,6 +201,22 @@ impl NpcBody {
comp::bird_medium::Body::random_with,
)
})
.or_else(|| {
parse(
s,
NpcKind::Clownfish,
&npc_names.fish_small,
comp::fish_small::Body::random_with,
)
})
.or_else(|| {
parse(
s,
NpcKind::Marlin,
&npc_names.fish_medium,
comp::fish_medium::Body::random_with,
)
})
.or_else(|| {
parse(
s,

View File

@ -58,10 +58,10 @@ impl Body {
quadruped_medium::Species::Horse => 180.0,
},
Body::BirdMedium(_) => 80.0,
Body::FishMedium(_) => 50.0,
Body::FishMedium(_) => 80.0,
Body::Dragon(_) => 250.0,
Body::BirdSmall(_) => 75.0,
Body::FishSmall(_) => 40.0,
Body::FishSmall(_) => 60.0,
Body::BipedLarge(_) => 75.0,
Body::Object(_) => 40.0,
Body::Golem(_) => 60.0,

View File

@ -1,50 +1,55 @@
use super::{super::Animation, FishMediumSkeleton, SkeletonAttr};
//use std::{f32::consts::PI, ops::Mul};
use super::super::vek::*;
use super::{
super::{vek::*, Animation},
FishMediumSkeleton, SkeletonAttr,
};
use std::f32::consts::PI;
pub struct IdleAnimation;
type IdleAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>);
impl Animation for IdleAnimation {
type Dependency = f64;
type Dependency = IdleAnimationDependency;
type Skeleton = FishMediumSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"fish_medium_idle\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_medium_idle")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
_global_time: Self::Dependency,
_anim_time: f64,
(_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency,
anim_time: f64,
_rate: &mut f32,
_skeleton_attr: &SkeletonAttr,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.head.scale = Vec3::one() / 10.88;
next.torso.scale = Vec3::one() * 1.01;
next.rear.scale = Vec3::one() * 0.98;
next.tail.scale = Vec3::one() / 11.0;
next.fin_l.scale = Vec3::one() / 11.0;
next.fin_r.scale = Vec3::one() / 10.5;
let slow = (anim_time as f32 * 3.5 + PI).sin();
let slowalt = (anim_time as f32 * 3.5 + PI + 0.2).sin();
next.head.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.head.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.chest_front.scale = Vec3::one() / 11.0;
next.torso.position = Vec3::new(0.0, 4.5, 2.0);
next.torso.orientation = Quaternion::rotation_x(0.0);
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation = Quaternion::rotation_z(slowalt * -0.1);
next.rear.position = Vec3::new(0.0, 3.1, -4.5);
next.rear.orientation = Quaternion::rotation_z(0.0);
next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
next.tail.position = Vec3::new(0.0, -13.0, 8.0) / 11.0;
next.tail.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.chest_front.position = Vec3::new(0.0, s_a.chest_front.0, s_a.chest_front.1) / 11.0;
next.chest_front.orientation = Quaternion::rotation_x(0.0);
next.fin_l.position = Vec3::new(0.0, -11.7, 11.0) / 11.0;
next.fin_l.orientation = Quaternion::rotation_y(0.0);
next.chest_back.position = Vec3::new(0.0, s_a.chest_back.0, s_a.chest_back.1);
next.chest_back.orientation = Quaternion::rotation_z(slowalt * 0.1);
next.fin_r.position = Vec3::new(0.0, 0.0, 12.0) / 11.0;
next.fin_r.orientation = Quaternion::rotation_y(0.0);
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
next.tail.orientation = Quaternion::rotation_z(slow * 0.1);
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
next.fin_l.orientation = Quaternion::rotation_z(slow * 0.1 - 0.1);
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
next.fin_r.orientation = Quaternion::rotation_z(-slow * 0.1 + 0.1);
next
}
}

View File

@ -1,50 +0,0 @@
use super::{super::Animation, FishMediumSkeleton, SkeletonAttr};
//use std::f32::consts::PI;
use super::super::vek::*;
pub struct JumpAnimation;
impl Animation for JumpAnimation {
type Dependency = (f32, f64);
type Skeleton = FishMediumSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"fish_medium_jump\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_medium_jump")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
_global_time: Self::Dependency,
_anim_time: f64,
_rate: &mut f32,
_skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.head.scale = Vec3::one() / 10.88;
next.torso.scale = Vec3::one() * 1.01;
next.rear.scale = Vec3::one() * 0.98;
next.tail.scale = Vec3::one() / 11.0;
next.fin_l.scale = Vec3::one() / 11.0;
next.fin_r.scale = Vec3::one() / 10.5;
next.head.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.head.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.torso.position = Vec3::new(0.0, 4.5, 2.0);
next.torso.orientation = Quaternion::rotation_x(0.0);
next.rear.position = Vec3::new(0.0, 3.1, -4.5);
next.rear.orientation = Quaternion::rotation_z(0.0);
next.tail.position = Vec3::new(0.0, -13.0, 8.0) / 11.0;
next.tail.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.fin_l.position = Vec3::new(0.0, -11.7, 11.0) / 11.0;
next.fin_l.orientation = Quaternion::rotation_y(0.0);
next.fin_r.position = Vec3::new(0.0, 0.0, 12.0) / 11.0;
next.fin_r.orientation = Quaternion::rotation_y(0.0);
next
}
}

View File

@ -1,9 +1,8 @@
pub mod idle;
pub mod jump;
pub mod run;
pub mod swim;
// Reexports
pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
pub use self::{idle::IdleAnimation, swim::SwimAnimation};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
@ -13,8 +12,9 @@ pub type Body = comp::fish_medium::Body;
skeleton_impls!(struct FishMediumSkeleton {
+ head,
+ torso,
+ rear,
+ jaw,
+ chest_front,
+ chest_back,
+ tail,
+ fin_l,
+ fin_r,
@ -24,7 +24,7 @@ impl Skeleton for FishMediumSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 6;
const BONE_COUNT: usize = 7;
#[cfg(feature = "use-dyn-lib")]
const COMPUTE_FN: &'static [u8] = b"fish_medium_compute_mats\0";
@ -34,22 +34,33 @@ impl Skeleton for FishMediumSkeleton {
base_mat: Mat4<f32>,
buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
) -> Vec3<f32> {
let torso_mat = base_mat * Mat4::<f32>::from(self.torso);
let rear_mat = torso_mat * Mat4::<f32>::from(self.rear);
let chest_front_mat = base_mat * Mat4::<f32>::from(self.chest_front);
let chest_back_mat = Mat4::<f32>::from(self.chest_back);
let head_mat = Mat4::<f32>::from(self.head);
*(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
make_bone(torso_mat * Mat4::<f32>::from(self.head)),
make_bone(torso_mat),
make_bone(rear_mat),
make_bone(rear_mat * Mat4::<f32>::from(self.tail)),
make_bone(rear_mat * Mat4::<f32>::from(self.fin_l)),
make_bone(rear_mat * Mat4::<f32>::from(self.fin_r)),
make_bone(chest_front_mat * head_mat),
make_bone(chest_front_mat * head_mat * Mat4::<f32>::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::<f32>::from(self.tail)),
make_bone(chest_front_mat * Mat4::<f32>::from(self.fin_l)),
make_bone(chest_front_mat * Mat4::<f32>::from(self.fin_r)),
];
Vec3::default()
}
}
pub struct SkeletonAttr;
pub struct SkeletonAttr {
head: (f32, f32),
jaw: (f32, f32),
chest_front: (f32, f32),
chest_back: (f32, f32),
tail: (f32, f32),
fin: (f32, f32, f32),
tempo: f32,
amplitude: f32,
}
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
type Error = ();
@ -63,9 +74,48 @@ impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
}
impl Default for SkeletonAttr {
fn default() -> Self { Self }
fn default() -> Self {
Self {
head: (0.0, 0.0),
jaw: (0.0, 0.0),
chest_front: (0.0, 0.0),
chest_back: (0.0, 0.0),
tail: (0.0, 0.0),
fin: (0.0, 0.0, 0.0),
tempo: 0.0,
amplitude: 0.0,
}
}
}
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(_body: &'a Body) -> Self { Self }
fn from(body: &'a Body) -> Self {
use comp::fish_medium::Species::*;
Self {
head: match (body.species, body.body_type) {
(Marlin, _) => (2.0, 1.5),
},
jaw: match (body.species, body.body_type) {
(Marlin, _) => (2.5, -3.0),
},
chest_front: match (body.species, body.body_type) {
(Marlin, _) => (0.0, 2.5),
},
chest_back: match (body.species, body.body_type) {
(Marlin, _) => (-1.0, 1.0),
},
tail: match (body.species, body.body_type) {
(Marlin, _) => (-7.0, 0.0),
},
fin: match (body.species, body.body_type) {
(Marlin, _) => (2.5, 1.0, 3.5),
},
tempo: match (body.species, body.body_type) {
(Marlin, _) => 4.0,
},
amplitude: match (body.species, body.body_type) {
(Marlin, _) => 4.0,
},
}
}
}

View File

@ -1,50 +0,0 @@
use super::{super::Animation, FishMediumSkeleton, SkeletonAttr};
//use std::f32::consts::PI;
use super::super::vek::*;
pub struct RunAnimation;
impl Animation for RunAnimation {
type Dependency = (f32, f64);
type Skeleton = FishMediumSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"fish_medium_run\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_medium_run")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
_global_time: Self::Dependency,
_anim_time: f64,
_rate: &mut f32,
_skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.head.scale = Vec3::one() / 10.88;
next.torso.scale = Vec3::one() * 1.01;
next.rear.scale = Vec3::one() * 0.98;
next.tail.scale = Vec3::one() / 11.0;
next.fin_l.scale = Vec3::one() / 11.0;
next.fin_r.scale = Vec3::one() / 10.5;
next.head.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.head.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.torso.position = Vec3::new(0.0, 4.5, 2.0);
next.torso.orientation = Quaternion::rotation_x(0.0);
next.rear.position = Vec3::new(0.0, 3.1, -4.5);
next.rear.orientation = Quaternion::rotation_z(0.0);
next.tail.position = Vec3::new(0.0, -13.0, 8.0) / 11.0;
next.tail.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.fin_l.position = Vec3::new(0.0, -11.7, 11.0) / 11.0;
next.fin_l.orientation = Quaternion::rotation_y(0.0);
next.fin_r.position = Vec3::new(0.0, 0.0, 12.0) / 11.0;
next.fin_r.orientation = Quaternion::rotation_y(0.0);
next
}
}

View File

@ -0,0 +1,74 @@
use super::{
super::{vek::*, Animation},
FishMediumSkeleton, SkeletonAttr,
};
use std::f32::consts::PI;
pub struct SwimAnimation;
type SwimAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>, f32);
impl Animation for SwimAnimation {
type Dependency = SwimAnimationDependency;
type Skeleton = FishMediumSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"fish_medium_swim\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_medium_swim")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(velocity, orientation, last_ori, _global_time, avg_vel, acc_vel): Self::Dependency,
_anim_time: f64,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let slowalt = (acc_vel as f32 * s_a.tempo / 1.5 + PI + 0.2).sin();
let fast = (acc_vel * s_a.tempo + PI).sin();
let fastalt = (acc_vel * s_a.tempo + PI + 0.2).sin();
let ori: Vec2<f32> = Vec2::from(orientation);
let last_ori = Vec2::from(last_ori);
let tilt = if ::vek::Vec2::new(ori, last_ori)
.map(|o| o.magnitude_squared())
.map(|m| m > 0.001 && m.is_finite())
.reduce_and()
&& ori.angle_between(last_ori).is_finite()
{
ori.angle_between(last_ori).min(0.8)
* last_ori.determine_side(Vec2::zero(), ori).signum()
} else {
0.0
} * 1.3;
let x_tilt = avg_vel.z.atan2(avg_vel.xy().magnitude());
let vel = (velocity.magnitude()).min(s_a.amplitude);
let slowvel = vel * 0.1;
next.chest_front.scale = Vec3::one() / 11.0;
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.head.orientation = Quaternion::rotation_z(slowalt * -0.1 + tilt * -2.0);
next.jaw.position = Vec3::new(0.0, s_a.jaw.0, s_a.jaw.1);
next.chest_front.position = Vec3::new(0.0, s_a.chest_front.0, s_a.chest_front.1) / 11.0;
next.chest_front.orientation = Quaternion::rotation_x(velocity.z.abs() * -0.005 + x_tilt)
* Quaternion::rotation_z(fast * vel * -0.02);
next.chest_back.position = Vec3::new(0.0, s_a.chest_back.0, s_a.chest_back.1);
next.chest_back.orientation = Quaternion::rotation_z(fastalt * slowvel + tilt * 2.0);
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
next.tail.orientation = Quaternion::rotation_z(fast * slowvel + tilt * 2.0);
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
next.fin_l.orientation = Quaternion::rotation_z(fast * slowvel - 0.1 + tilt * -0.5);
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
next.fin_r.orientation = Quaternion::rotation_z(fast * -slowvel + 0.1 + tilt * -0.5);
next
}
}

View File

@ -1,34 +1,45 @@
use super::{super::Animation, FishSmallSkeleton, SkeletonAttr};
//use std::{f32::consts::PI, ops::Mul};
use super::super::vek::*;
use super::{
super::{vek::*, Animation},
FishSmallSkeleton, SkeletonAttr,
};
use std::f32::consts::PI;
pub struct IdleAnimation;
type IdleAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>);
impl Animation for IdleAnimation {
type Dependency = f64;
type Dependency = IdleAnimationDependency;
type Skeleton = FishSmallSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"fish_small_idle\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_idle")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
_global_time: Self::Dependency,
_anim_time: f64,
(_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency,
anim_time: f64,
_rate: &mut f32,
_skeleton_attr: &SkeletonAttr,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.torso.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.torso.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.torso.scale = Vec3::one() / 10.88;
let slow = (anim_time as f32 * 3.5 + PI).sin();
next.tail.position = Vec3::new(0.0, 4.5, 2.0);
next.tail.orientation = Quaternion::rotation_x(0.0);
next.tail.scale = Vec3::one() * 1.01;
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.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
next.tail.orientation = Quaternion::rotation_z(slow * 0.1);
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
next.fin_l.orientation = Quaternion::rotation_z(slow * 0.1 - 0.1);
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
next.fin_r.orientation = Quaternion::rotation_z(-slow * 0.1 + 0.1);
next
}
}

View File

@ -1,34 +0,0 @@
use super::{super::Animation, FishSmallSkeleton, SkeletonAttr};
//use std::f32::consts::PI;
use super::super::vek::*;
pub struct JumpAnimation;
impl Animation for JumpAnimation {
type Dependency = (f32, f64);
type Skeleton = FishSmallSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"fish_small_jump\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_jump")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
_global_time: Self::Dependency,
_anim_time: f64,
_rate: &mut f32,
_skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.torso.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.torso.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.torso.scale = Vec3::one() / 10.88;
next.tail.position = Vec3::new(0.0, 4.5, 2.0);
next.tail.orientation = Quaternion::rotation_x(0.0);
next.tail.scale = Vec3::one() * 1.01;
next
}
}

View File

@ -1,9 +1,8 @@
pub mod idle;
pub mod jump;
pub mod run;
pub mod swim;
// Reexports
pub use self::{idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation};
pub use self::{idle::IdleAnimation, swim::SwimAnimation};
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
use common::comp::{self};
@ -12,36 +11,45 @@ use core::convert::TryFrom;
pub type Body = comp::fish_small::Body;
skeleton_impls!(struct FishSmallSkeleton {
+ torso,
+ chest,
+ tail,
+ fin_l,
+ fin_r,
});
impl Skeleton for FishSmallSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 2;
const BONE_COUNT: usize = 4;
#[cfg(feature = "use-dyn-lib")]
const COMPUTE_FN: &'static [u8] = b"fish_small_compute_mats\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_compute_mats")]
fn compute_matrices_inner(
&self,
base_mat: Mat4<f32>,
buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
) -> Vec3<f32> {
let torso_mat = base_mat * Mat4::<f32>::from(self.torso);
let chest_mat = base_mat * Mat4::<f32>::from(self.chest);
*(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
make_bone(torso_mat),
make_bone(torso_mat * Mat4::<f32>::from(self.tail)),
make_bone(chest_mat),
make_bone(chest_mat * Mat4::<f32>::from(self.tail)),
make_bone(chest_mat * Mat4::<f32>::from(self.fin_l)),
make_bone(chest_mat * Mat4::<f32>::from(self.fin_r)),
];
Vec3::default()
}
}
pub struct SkeletonAttr;
pub struct SkeletonAttr {
chest: (f32, f32),
tail: (f32, f32),
fin: (f32, f32, f32),
tempo: f32,
amplitude: f32,
}
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
type Error = ();
@ -55,9 +63,36 @@ impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
}
impl Default for SkeletonAttr {
fn default() -> Self { Self }
fn default() -> Self {
Self {
chest: (0.0, 0.0),
tail: (0.0, 0.0),
fin: (0.0, 0.0, 0.0),
tempo: 0.0,
amplitude: 0.0,
}
}
}
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(_body: &'a Body) -> Self { Self }
fn from(body: &'a Body) -> Self {
use comp::fish_small::Species::*;
Self {
chest: match (body.species, body.body_type) {
(Clownfish, _) => (0.0, 5.0),
},
tail: match (body.species, body.body_type) {
(Clownfish, _) => (-7.5, -0.5),
},
fin: match (body.species, body.body_type) {
(Clownfish, _) => (2.0, 0.5, 1.0),
},
tempo: match (body.species, body.body_type) {
(Clownfish, _) => 5.0,
},
amplitude: match (body.species, body.body_type) {
(Clownfish, _) => 4.0,
},
}
}
}

View File

@ -1,34 +0,0 @@
use super::{super::Animation, FishSmallSkeleton, SkeletonAttr};
//use std::{f32::consts::PI, ops::Mul};
use super::super::vek::*;
pub struct RunAnimation;
impl Animation for RunAnimation {
type Dependency = (f32, f64);
type Skeleton = FishSmallSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"fish_small_run\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_run")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(_velocity, _global_time): Self::Dependency,
_anim_time: f64,
_rate: &mut f32,
_skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.torso.position = Vec3::new(0.0, 7.5, 15.0) / 11.0;
next.torso.orientation = Quaternion::rotation_z(0.0) * Quaternion::rotation_x(0.0);
next.torso.scale = Vec3::one() / 10.88;
next.tail.position = Vec3::new(0.0, 4.5, 2.0);
next.tail.orientation = Quaternion::rotation_x(0.0);
next.tail.scale = Vec3::one() * 1.01;
next
}
}

View File

@ -0,0 +1,64 @@
use super::{
super::{vek::*, Animation},
FishSmallSkeleton, SkeletonAttr,
};
use std::f32::consts::PI;
pub struct SwimAnimation;
type SwimAnimationDependency = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f64, Vec3<f32>, f32);
impl Animation for SwimAnimation {
type Dependency = SwimAnimationDependency;
type Skeleton = FishSmallSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"fish_small_swim\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "fish_small_swim")]
fn update_skeleton_inner(
skeleton: &Self::Skeleton,
(velocity, orientation, last_ori, _global_time, avg_vel, acc_vel): Self::Dependency,
_anim_time: f64,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let fast = (acc_vel * s_a.tempo + PI).sin();
let ori: Vec2<f32> = Vec2::from(orientation);
let last_ori = Vec2::from(last_ori);
let tilt = if ::vek::Vec2::new(ori, last_ori)
.map(|o| o.magnitude_squared())
.map(|m| m > 0.001 && m.is_finite())
.reduce_and()
&& ori.angle_between(last_ori).is_finite()
{
ori.angle_between(last_ori).min(0.8)
* last_ori.determine_side(Vec2::zero(), ori).signum()
} else {
0.0
} * 1.3;
let x_tilt = avg_vel.z.atan2(avg_vel.xy().magnitude());
let vel = (velocity.magnitude()).min(s_a.amplitude);
let slowvel = vel * 0.1;
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.chest.orientation = Quaternion::rotation_x(velocity.z.abs() * -0.005 + x_tilt)
* Quaternion::rotation_z(fast * -0.1);
next.tail.position = Vec3::new(0.0, s_a.tail.0, s_a.tail.1);
next.tail.orientation = Quaternion::rotation_z(fast * -1.0 * slowvel + tilt * 2.0);
next.fin_l.position = Vec3::new(-s_a.fin.0, s_a.fin.1, s_a.fin.2);
next.fin_l.orientation = Quaternion::rotation_z(fast * 0.6 * slowvel - 0.3 + tilt * -0.5);
next.fin_r.position = Vec3::new(s_a.fin.0, s_a.fin.1, s_a.fin.2);
next.fin_r.orientation = Quaternion::rotation_z(fast * -0.6 * slowvel + 0.3 + tilt * -0.5);
next
}
}

View File

@ -6,7 +6,8 @@ use common::{
bird_medium::{self, BodyType as BMBodyType, Species as BMSpecies},
bird_small,
dragon::{self, BodyType as DBodyType, Species as DSpecies},
fish_medium, fish_small,
fish_medium::{self, BodyType as FMBodyType, Species as FMSpecies},
fish_small::{self, BodyType as FSBodyType, Species as FSSpecies},
golem::{self, BodyType as GBodyType, Species as GSpecies},
humanoid::{self, Body, BodyType, EyeColor, Skin, Species},
object,
@ -2086,17 +2087,253 @@ impl TheropodLateralSpec {
}
}
////
#[derive(Deserialize)]
struct FishMediumCentralSpec(HashMap<(FMSpecies, FMBodyType), SidedFMCentralVoxSpec>);
#[derive(Deserialize)]
struct SidedFMCentralVoxSpec {
head: FishMediumCentralSubSpec,
jaw: FishMediumCentralSubSpec,
chest_front: FishMediumCentralSubSpec,
chest_back: FishMediumCentralSubSpec,
tail: FishMediumCentralSubSpec,
}
#[derive(Deserialize)]
struct FishMediumCentralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
central: VoxSimple,
}
#[derive(Deserialize)]
struct FishMediumLateralSpec(HashMap<(FMSpecies, FMBodyType), SidedFMLateralVoxSpec>);
#[derive(Deserialize)]
struct SidedFMLateralVoxSpec {
fin_l: FishMediumLateralSubSpec,
fin_r: FishMediumLateralSubSpec,
}
#[derive(Deserialize)]
struct FishMediumLateralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
lateral: VoxSimple,
}
make_vox_spec!(
fish_medium::Body,
struct FishMediumSpec {},
|FigureKey { body, .. }, _spec| {
struct FishMediumSpec {
central: FishMediumCentralSpec = "voxygen.voxel.fish_medium_central_manifest",
lateral: FishMediumLateralSpec = "voxygen.voxel.fish_medium_lateral_manifest",
},
|FigureKey { body, .. }, spec| {
[
Some(mesh_fish_medium_head(body.head)),
Some(mesh_fish_medium_torso(body.torso)),
Some(mesh_fish_medium_rear(body.rear)),
Some(mesh_fish_medium_tail(body.tail)),
Some(mesh_fish_medium_fin_l(body.fin_l)),
Some(mesh_fish_medium_fin_r(body.fin_r)),
Some(spec.central.asset.mesh_head(
body.species,
body.body_type,
)),
Some(spec.central.asset.mesh_jaw(
body.species,
body.body_type,
)),
Some(spec.central.asset.mesh_chest_front(
body.species,
body.body_type,
)),
Some(spec.central.asset.mesh_chest_back(
body.species,
body.body_type,
)),
Some(spec.central.asset.mesh_tail(
body.species,
body.body_type,
)),
Some(spec.lateral.asset.mesh_fin_l(
body.species,
body.body_type,
)),
Some(spec.lateral.asset.mesh_fin_r(
body.species,
body.body_type,
)),
None,
None,
None,
None,
None,
None,
None,
None,
None,
]
},
);
impl FishMediumCentralSpec {
fn mesh_head(&self, species: FMSpecies, body_type: FMBodyType) -> 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_jaw(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
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));
},
};
let central = graceful_load_segment(&spec.jaw.central.0);
(central, Vec3::from(spec.jaw.offset))
}
fn mesh_chest_front(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No front 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_front.central.0);
(central, Vec3::from(spec.chest_front.offset))
}
fn mesh_chest_back(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No back 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_back.central.0);
(central, Vec3::from(spec.chest_back.offset))
}
fn mesh_tail(&self, species: FMSpecies, body_type: FMBodyType) -> 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))
}
}
impl FishMediumLateralSpec {
fn mesh_fin_l(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No fin 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.fin_l.lateral.0);
(lateral, Vec3::from(spec.fin_l.offset))
}
fn mesh_fin_r(&self, species: FMSpecies, body_type: FMBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No fin 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.fin_r.lateral.0);
(lateral, Vec3::from(spec.fin_r.offset))
}
}
////
#[derive(Deserialize)]
struct FishSmallCentralSpec(HashMap<(FSSpecies, FSBodyType), SidedFSCentralVoxSpec>);
#[derive(Deserialize)]
struct SidedFSCentralVoxSpec {
chest: FishSmallCentralSubSpec,
tail: FishSmallCentralSubSpec,
}
#[derive(Deserialize)]
struct FishSmallCentralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
central: VoxSimple,
}
#[derive(Deserialize)]
struct FishSmallLateralSpec(HashMap<(FSSpecies, FSBodyType), SidedFSLateralVoxSpec>);
#[derive(Deserialize)]
struct SidedFSLateralVoxSpec {
fin_l: FishSmallLateralSubSpec,
fin_r: FishSmallLateralSubSpec,
}
#[derive(Deserialize)]
struct FishSmallLateralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
lateral: VoxSimple,
}
make_vox_spec!(
fish_small::Body,
struct FishSmallSpec {
central: FishSmallCentralSpec = "voxygen.voxel.fish_small_central_manifest",
lateral: FishSmallLateralSpec = "voxygen.voxel.fish_small_lateral_manifest",
},
|FigureKey { body, .. }, spec| {
[
Some(spec.central.asset.mesh_chest(
body.species,
body.body_type,
)),
Some(spec.central.asset.mesh_tail(
body.species,
body.body_type,
)),
Some(spec.lateral.asset.mesh_fin_l(
body.species,
body.body_type,
)),
Some(spec.lateral.asset.mesh_fin_r(
body.species,
body.body_type,
)),
None,
None,
None,
None,
None,
@ -2111,58 +2348,72 @@ make_vox_spec!(
},
);
fn mesh_fish_medium_head(head: fish_medium::Head) -> BoneMeshes {
load_mesh(
match head {
fish_medium::Head::Default => "npc.marlin.head",
},
Vec3::new(-7.0, -6.0, -6.0),
)
impl FishSmallCentralSpec {
fn mesh_chest(&self, species: FSSpecies, body_type: FSBodyType) -> 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_tail(&self, species: FSSpecies, body_type: FSBodyType) -> 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_fish_medium_torso(torso: fish_medium::Torso) -> BoneMeshes {
load_mesh(
match torso {
fish_medium::Torso::Default => "npc.marlin.torso",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
impl FishSmallLateralSpec {
fn mesh_fin_l(&self, species: FSSpecies, body_type: FSBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No fin 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.fin_l.lateral.0);
fn mesh_fish_medium_rear(rear: fish_medium::Rear) -> BoneMeshes {
load_mesh(
match rear {
fish_medium::Rear::Default => "npc.marlin.rear",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
(lateral, Vec3::from(spec.fin_l.offset))
}
fn mesh_fish_medium_tail(tail: fish_medium::Tail) -> BoneMeshes {
load_mesh(
match tail {
fish_medium::Tail::Default => "npc.marlin.tail",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
fn mesh_fin_r(&self, species: FSSpecies, body_type: FSBodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No fin 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.fin_r.lateral.0);
fn mesh_fish_medium_fin_l(fin_l: fish_medium::FinL) -> BoneMeshes {
load_mesh(
match fin_l {
fish_medium::FinL::Default => "npc.marlin.fin_l",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
fn mesh_fish_medium_fin_r(fin_r: fish_medium::FinR) -> BoneMeshes {
load_mesh(
match fin_r {
fish_medium::FinR::Default => "npc.marlin.fin_r",
},
Vec3::new(-7.0, -6.0, -6.0),
)
(lateral, Vec3::from(spec.fin_r.offset))
}
}
////
@ -2583,49 +2834,7 @@ fn mesh_bird_small_wing_r(wing_r: bird_small::WingR) -> BoneMeshes {
Vec3::new(-7.0, -6.0, -6.0),
)
}
////
make_vox_spec!(
fish_small::Body,
struct FishSmallSpec {},
|FigureKey { body, .. }, _spec| {
[
Some(mesh_fish_small_torso(body.torso)),
Some(mesh_fish_small_tail(body.tail)),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
]
},
);
fn mesh_fish_small_torso(torso: fish_small::Torso) -> BoneMeshes {
load_mesh(
match torso {
fish_small::Torso::Default => "npc.cardinalfish.torso",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
fn mesh_fish_small_tail(tail: fish_small::Tail) -> BoneMeshes {
load_mesh(
match tail {
fish_small::Tail::Default => "npc.cardinalfish.tail",
},
Vec3::new(-7.0, -6.0, -6.0),
)
}
////
#[derive(Deserialize)]
struct BipedLargeCentralSpec(HashMap<(BLSpecies, BLBodyType), SidedBLCentralVoxSpec>);

View File

@ -2179,35 +2179,25 @@ impl FigureMgr {
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
physics.in_liquid.is_some(), // In water
) {
// Standing
(true, false, false) => anim::fish_medium::IdleAnimation::update_skeleton(
// Idle
(_, false, _) => anim::fish_medium::IdleAnimation::update_skeleton(
&FishMediumSkeleton::default(),
time,
(vel.0, ori, state.last_ori, time, state.avg_vel),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// Running
(true, true, false) => anim::fish_medium::RunAnimation::update_skeleton(
// Swim
(_, true, _) => anim::fish_medium::SwimAnimation::update_skeleton(
&FishMediumSkeleton::default(),
(vel.0.magnitude(), time),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// In air
(false, _, false) => anim::fish_medium::JumpAnimation::update_skeleton(
&FishMediumSkeleton::default(),
(vel.0.magnitude(), time),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// TODO!
_ => anim::fish_medium::IdleAnimation::update_skeleton(
&FishMediumSkeleton::default(),
time,
(
vel.0,
ori,
state.last_ori,
time,
state.avg_vel,
state.acc_vel,
),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
@ -2574,35 +2564,25 @@ impl FigureMgr {
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
physics.in_liquid.is_some(), // In water
) {
// Standing
(true, false, false) => anim::fish_small::IdleAnimation::update_skeleton(
// Idle
(_, false, _) => anim::fish_small::IdleAnimation::update_skeleton(
&FishSmallSkeleton::default(),
time,
(vel.0, ori, state.last_ori, time, state.avg_vel),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// Running
(true, true, false) => anim::fish_small::RunAnimation::update_skeleton(
// Swim
(_, true, _) => anim::fish_small::SwimAnimation::update_skeleton(
&FishSmallSkeleton::default(),
(vel.0.magnitude(), time),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// In air
(false, _, false) => anim::fish_small::JumpAnimation::update_skeleton(
&FishSmallSkeleton::default(),
(vel.0.magnitude(), time),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// TODO!
_ => anim::fish_small::IdleAnimation::update_skeleton(
&FishSmallSkeleton::default(),
time,
(
vel.0,
ori,
state.last_ori,
time,
state.avg_vel,
state.acc_vel,
),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
@ -3761,6 +3741,7 @@ pub struct FigureStateMeta {
avg_vel: anim::vek::Vec3<f32>,
last_light: f32,
last_glow: f32,
acc_vel: f32,
}
impl FigureStateMeta {
@ -3807,6 +3788,7 @@ impl<S: Skeleton> FigureState<S> {
avg_vel: anim::vek::Vec3::zero(),
last_light: 1.0,
last_glow: 0.0,
acc_vel: 0.0,
},
skeleton,
}
@ -3935,6 +3917,13 @@ impl<S: Skeleton> FigureState<S> {
self.avg_vel = (1.0 - smoothing) * self.avg_vel + smoothing * (pos - last_pos) / dt;
}
self.last_pos = Some(pos);
// Can potentially overflow
if self.avg_vel.magnitude_squared() != 0.0 {
self.acc_vel += self.avg_vel.magnitude() * dt;
} else {
self.acc_vel = 0.0;
}
}
pub fn locals(&self) -> &Consts<FigureLocals> { &self.locals }

View File

@ -1,8 +1,8 @@
use crate::{column::ColumnSample, sim::SimChunk, IndexRef, CONFIG};
use common::{
comp::{
biped_large, bird_medium, quadruped_low, quadruped_medium, quadruped_small, theropod,
Alignment,
biped_large, bird_medium, fish_medium, fish_small, quadruped_low, quadruped_medium,
quadruped_small, theropod, Alignment,
},
generation::{ChunkSupplement, EntityInfo},
terrain::Block,
@ -50,10 +50,10 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
1 => {
theropod::Body::random_with(rng, &theropod::Species::Snowraptor).into()
},
_ => quadruped_medium::Body::random_with(
rng,
&quadruped_medium::Species::Roshwalr,
)
_ => quadruped_medium::Body {
species: quadruped_medium::Species::Roshwalr,
body_type: quadruped_medium::BodyType::Male,
}
.into(),
})
.with_alignment(Alignment::Enemy)
@ -697,7 +697,7 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
* 0.2
},
},
// Desert river solitary wild
// Desert river solitary enemy
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
@ -718,6 +718,28 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
}
},
},
// Desert secret solitary enemy
Entry {
make_entity: |pos, _rng| {
EntityInfo::at(pos)
.with_body(
quadruped_medium::Body {
species: quadruped_medium::Species::Roshwalr,
body_type: quadruped_medium::BodyType::Female,
}
.into(),
)
.with_alignment(Alignment::Enemy)
},
group_size: 1..3,
is_underwater: false,
get_density: |c, _col| {
close(c.temp, CONFIG.desert_temp + 0.2, 0.3)
* close(c.humidity, CONFIG.desert_hum, 0.5)
* BASE_DENSITY
* 0.01
},
},
// Desert solitary wild
Entry {
make_entity: |pos, rng| {
@ -761,6 +783,24 @@ pub fn apply_wildlife_supplement<'a, R: Rng>(
close(c.temp, CONFIG.desert_temp + 0.2, 0.3) * BASE_DENSITY * 5.0
},
},
// Underwater
Entry {
make_entity: |pos, rng| {
EntityInfo::at(pos)
.with_body(match rng.gen_range(0, 2) {
0 => fish_medium::Body::random_with(rng, &fish_medium::Species::Marlin)
.into(),
_ => fish_small::Body::random_with(rng, &fish_small::Species::Clownfish)
.into(),
})
.with_alignment(Alignment::Wild)
},
group_size: 3..5,
is_underwater: true,
get_density: |c, col| {
close(c.temp, CONFIG.temperate_temp, 1.0) * col.tree_density * BASE_DENSITY * 5.0
},
},
];
for y in 0..vol.size_xy().y as i32 {