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 4bdd84ab46
47 changed files with 999 additions and 517 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"),
),
),
})

BIN
assets/voxygen/voxel/npc/clownfish/male/chest.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/clownfish/male/fin_l.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/clownfish/male/fin_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/clownfish/male/tail.vox (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/fin_l.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/fin_r.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/head.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/male/chest_back.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/male/chest_front.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/male/fin_l.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/male/fin_r.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/male/head.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/male/tail.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/rear.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/tail.vox (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/voxel/npc/marlin/torso.vox (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/voxygen/voxel/npc/roshwalr/female/head.vox (Stored with Git LFS) Normal file

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 {