Adds arthropod skeleton

This commit is contained in:
Snowram 2021-07-25 17:16:57 +02:00
parent 59d195b9bc
commit f67bf2a539
23 changed files with 1337 additions and 9 deletions

View File

@ -1207,5 +1207,19 @@
generic: "Deadwood" generic: "Deadwood"
), ),
) )
),
arthropod: (
body: (
keyword: "arthropod",
names_0: [
"Shelob"
]
),
species: (
tarantula: (
keyword: "tarantula",
generic: "Tarantula"
) )
)
),
) )

View File

@ -0,0 +1,22 @@
({
(Tarantula, Male): (
head: (
offset: (-4.5, 0.0, -5.0),
central: ("npc.tarantula.male.head"),
),
chest: (
offset: (-5.5, -2.0, -3.0),
central: ("npc.tarantula.male.chest"),
),
),
(Tarantula, Female): (
head: (
offset: (-4.5, 0.0, -5.0),
central: ("npc.tarantula.male.head"),
),
chest: (
offset: (-5.5, -2.0, -3.0),
central: ("npc.tarantula.male.chest"),
),
),
})

View File

@ -0,0 +1,118 @@
({
(Tarantula, Male): (
mandible_l: (
offset: (-4.0, -2.0, -9.0),
lateral: ("npc.tarantula.male.mandible_l"),
),
mandible_r: (
offset: (0.0, -2.0, -9.0),
lateral: ("npc.tarantula.male.mandible_r"),
),
wing_fl: (
offset: (-6.0, -4.5, -8.0),
lateral: ("npc.tarantula.male.wing_fl"),
),
wing_fr: (
offset: (0.0, -4.5, -8.0),
lateral: ("npc.tarantula.male.wing_fr"),
),
wing_bl: (
offset: (-11.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.wing_bl"),
),
wing_br: (
offset: (-11.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.wing_br"),
),
leg_fl: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_fl"),
),
leg_fr: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_fr"),
),
leg_fcl: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_fbl"),
),
leg_fcr: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_fbr"),
),
leg_bcl: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_bcl"),
),
leg_bcr: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_bcr"),
),
leg_bl: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_bl"),
),
leg_br: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_br"),
),
),
(Tarantula, Female): (
mandible_l: (
offset: (-4.0, -2.0, -9.0),
lateral: ("npc.tarantula.male.mandible_l"),
),
mandible_r: (
offset: (0.0, -2.0, -9.0),
lateral: ("npc.tarantula.male.mandible_r"),
),
wing_fl: (
offset: (-6.0, -4.5, -8.0),
lateral: ("npc.tarantula.male.wing_fl"),
),
wing_fr: (
offset: (0.0, -4.5, -8.0),
lateral: ("npc.tarantula.male.wing_fr"),
),
wing_bl: (
offset: (-11.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.wing_bl"),
),
wing_br: (
offset: (-11.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.wing_br"),
),
leg_fl: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_fl"),
),
leg_fr: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_fr"),
),
leg_fcl: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_fbl"),
),
leg_fcr: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_fbr"),
),
leg_bcl: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_bcl"),
),
leg_bcr: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_bcr"),
),
leg_bl: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_bl"),
),
leg_br: (
offset: (0.0, -1.0, -8.0),
lateral: ("npc.tarantula.male.leg_br"),
),
),
})

View File

@ -172,6 +172,7 @@ lazy_static! {
theropod, theropod,
dragon, dragon,
golem, golem,
arthropod,
); );
souls souls

View File

@ -267,6 +267,7 @@ impl<'a> From<&'a Body> for Psyche {
Body::Theropod(_) => 0.0, Body::Theropod(_) => 0.0,
Body::Ship(_) => 0.0, Body::Ship(_) => 0.0,
Body::Dragon(_) => 0.0, Body::Dragon(_) => 0.0,
Body::Arthropod(_) => 1.0,
}, },
sight_dist: 40.0, sight_dist: 40.0,
listen_dist: 30.0, listen_dist: 30.0,

View File

@ -1,3 +1,4 @@
pub mod arthropod;
pub mod biped_large; pub mod biped_large;
pub mod biped_small; pub mod biped_small;
pub mod bird_large; pub mod bird_large;
@ -48,6 +49,7 @@ make_case_elim!(
Theropod(body: theropod::Body) = 12, Theropod(body: theropod::Body) = 12,
QuadrupedLow(body: quadruped_low::Body) = 13, QuadrupedLow(body: quadruped_low::Body) = 13,
Ship(body: ship::Body) = 14, Ship(body: ship::Body) = 14,
Arthropod(body: arthropod::Body) = 15,
} }
); );
@ -85,6 +87,7 @@ pub struct AllBodies<BodyMeta, SpeciesMeta> {
pub theropod: BodyData<BodyMeta, theropod::AllSpecies<SpeciesMeta>>, pub theropod: BodyData<BodyMeta, theropod::AllSpecies<SpeciesMeta>>,
pub quadruped_low: BodyData<BodyMeta, quadruped_low::AllSpecies<SpeciesMeta>>, pub quadruped_low: BodyData<BodyMeta, quadruped_low::AllSpecies<SpeciesMeta>>,
pub ship: BodyData<BodyMeta, ()>, pub ship: BodyData<BodyMeta, ()>,
pub arthropod: BodyData<BodyMeta, arthropod::AllSpecies<SpeciesMeta>>,
} }
/// Can only retrieve body metadata by direct index. /// Can only retrieve body metadata by direct index.
@ -107,6 +110,7 @@ impl<BodyMeta, SpeciesMeta> core::ops::Index<NpcKind> for AllBodies<BodyMeta, Sp
NpcKind::Archaeos => &self.theropod.body, NpcKind::Archaeos => &self.theropod.body,
NpcKind::Reddragon => &self.dragon.body, NpcKind::Reddragon => &self.dragon.body,
NpcKind::Crocodile => &self.quadruped_low.body, NpcKind::Crocodile => &self.quadruped_low.body,
NpcKind::Tarantula => &self.arthropod.body,
} }
} }
} }
@ -132,6 +136,7 @@ impl<'a, BodyMeta, SpeciesMeta> core::ops::Index<&'a Body> for AllBodies<BodyMet
Body::Golem(_) => &self.golem.body, Body::Golem(_) => &self.golem.body,
Body::Theropod(_) => &self.theropod.body, Body::Theropod(_) => &self.theropod.body,
Body::QuadrupedLow(_) => &self.quadruped_low.body, Body::QuadrupedLow(_) => &self.quadruped_low.body,
Body::Arthropod(_) => &self.arthropod.body,
Body::Ship(_) => &self.ship.body, Body::Ship(_) => &self.ship.body,
} }
} }
@ -290,6 +295,7 @@ impl Body {
theropod::Species::Yale => 1_000.0, theropod::Species::Yale => 1_000.0,
}, },
Body::Ship(ship) => ship.mass().0, Body::Ship(ship) => ship.mass().0,
Body::Arthropod(body) => 500.0,
}; };
Mass(m) Mass(m)
} }
@ -396,6 +402,7 @@ impl Body {
theropod::Species::Woodraptor => Vec3::new(2.0, 3.0, 2.6), theropod::Species::Woodraptor => Vec3::new(2.0, 3.0, 2.6),
theropod::Species::Yale => Vec3::new(1.5, 3.2, 4.0), theropod::Species::Yale => Vec3::new(1.5, 3.2, 4.0),
}, },
Body::Arthropod(body) => Vec3::new(1.0, 1.0, 1.0),
} }
} }
@ -640,6 +647,7 @@ impl Body {
quadruped_low::Species::Deadwood => 120, quadruped_low::Species::Deadwood => 120,
_ => 70, _ => 70,
}, },
Body::Arthropod(_) => 100,
Body::Ship(_) => 1000, Body::Ship(_) => 1000,
} }
} }

View File

@ -0,0 +1,66 @@
use rand::{seq::SliceRandom, thread_rng};
use serde::{Deserialize, Serialize};
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Body {
pub species: Species,
pub body_type: BodyType,
}
impl Body {
pub fn random() -> Self {
let mut rng = thread_rng();
let species = *(&ALL_SPECIES).choose(&mut rng).unwrap();
Self::random_with(&mut rng, &species)
}
#[inline]
pub fn random_with(rng: &mut impl rand::Rng, &species: &Species) -> Self {
let body_type = *(&ALL_BODY_TYPES).choose(rng).unwrap();
Self { species, body_type }
}
}
impl From<Body> for super::Body {
fn from(body: Body) -> Self { super::Body::Arthropod(body) }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum Species {
Tarantula = 0,
}
/// Data representing per-species generic data.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AllSpecies<SpeciesMeta> {
pub tarantula: 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::Tarantula => &self.tarantula,
}
}
}
pub const ALL_SPECIES: [Species; 1] = [Species::Tarantula];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Species;
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]
pub enum BodyType {
Female = 0,
Male = 1,
}
pub const ALL_BODY_TYPES: [BodyType; 2] = [BodyType::Female, BodyType::Male];

View File

@ -229,7 +229,8 @@ impl Body {
Body::Theropod(_) Body::Theropod(_)
| Body::QuadrupedMedium(_) | Body::QuadrupedMedium(_)
| Body::QuadrupedSmall(_) | Body::QuadrupedSmall(_)
| Body::QuadrupedLow(_) => { | Body::QuadrupedLow(_)
| Body::Arthropod(_) => {
let dim = self.dimensions().map(|a| a * 0.5); let dim = self.dimensions().map(|a| a * 0.5);
let cd: f32 = if matches!(self, Body::QuadrupedLow(_)) { let cd: f32 = if matches!(self, Body::QuadrupedLow(_)) {
0.7 0.7

View File

@ -3,7 +3,7 @@
use crate::{ use crate::{
assets::{self, AssetExt}, assets::{self, AssetExt},
comp::{ comp::{
biped_large, biped_small, bird_large, golem, arthropod, biped_large, biped_small, bird_large, golem,
inventory::{ inventory::{
loadout::Loadout, loadout::Loadout,
slot::{ArmorSlot, EquipSlot}, slot::{ArmorSlot, EquipSlot},
@ -265,6 +265,11 @@ fn default_main_tool(body: &Body) -> Item {
"common.items.npc_weapons.unique.theropodbasic", "common.items.npc_weapons.unique.theropodbasic",
)), )),
}, },
Body::Arthropod(arthropod) => match arthropod.species {
_ => Some(Item::new_from_asset_expect(
"common.items.npc_weapons.unique.theropodbasic",
)),
},
Body::BipedLarge(biped_large) => match (biped_large.species, biped_large.body_type) { Body::BipedLarge(biped_large) => match (biped_large.species, biped_large.body_type) {
(biped_large::Species::Occultsaurok, _) => Some(Item::new_from_asset_expect( (biped_large::Species::Occultsaurok, _) => Some(Item::new_from_asset_expect(
"common.items.npc_weapons.staff.saurok_staff", "common.items.npc_weapons.staff.saurok_staff",
@ -752,6 +757,7 @@ mod tests {
theropod: Theropod, theropod: Theropod,
dragon: Dragon, dragon: Dragon,
golem: Golem, golem: Golem,
arthropod: Arthropod,
); );
} }

View File

@ -59,9 +59,9 @@ pub use self::{
aura::{Aura, AuraChange, AuraKind, Auras}, aura::{Aura, AuraChange, AuraKind, Auras},
beam::{Beam, BeamSegment}, beam::{Beam, BeamSegment},
body::{ body::{
biped_large, biped_small, bird_large, bird_medium, dragon, fish_medium, fish_small, golem, arthropod, biped_large, biped_small, bird_large, bird_medium, dragon, fish_medium,
humanoid, object, quadruped_low, quadruped_medium, quadruped_small, ship, theropod, fish_small, golem, humanoid, object, quadruped_low, quadruped_medium, quadruped_small,
AllBodies, Body, BodyData, ship, theropod, AllBodies, Body, BodyData,
}, },
buff::{ buff::{
Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs, Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs,

View File

@ -406,6 +406,7 @@ impl EntityInfo {
Body::QuadrupedLow(body) => Some(get_npc_name(&npc_names.quadruped_low, body.species)), Body::QuadrupedLow(body) => Some(get_npc_name(&npc_names.quadruped_low, body.species)),
Body::Golem(body) => Some(get_npc_name(&npc_names.golem, body.species)), Body::Golem(body) => Some(get_npc_name(&npc_names.golem, body.species)),
Body::BipedLarge(body) => Some(get_npc_name(&npc_names.biped_large, body.species)), Body::BipedLarge(body) => Some(get_npc_name(&npc_names.biped_large, body.species)),
Body::Arthropod(body) => Some(get_npc_name(&npc_names.arthropod, body.species)),
_ => None, _ => None,
}; };
self.name = name.map(str::to_owned); self.name = name.map(str::to_owned);

View File

@ -22,9 +22,10 @@ pub enum NpcKind {
StoneGolem, StoneGolem,
Reddragon, Reddragon,
Crocodile, Crocodile,
Tarantula,
} }
pub const ALL_NPCS: [NpcKind; 13] = [ pub const ALL_NPCS: [NpcKind; 14] = [
NpcKind::Humanoid, NpcKind::Humanoid,
NpcKind::Wolf, NpcKind::Wolf,
NpcKind::Pig, NpcKind::Pig,
@ -38,6 +39,7 @@ pub const ALL_NPCS: [NpcKind; 13] = [
NpcKind::StoneGolem, NpcKind::StoneGolem,
NpcKind::Reddragon, NpcKind::Reddragon,
NpcKind::Crocodile, NpcKind::Crocodile,
NpcKind::Tarantula,
]; ];
/// Body-specific NPC name metadata. /// Body-specific NPC name metadata.
@ -133,6 +135,7 @@ pub fn kind_to_body(kind: NpcKind) -> Body {
NpcKind::StoneGolem => comp::golem::Body::random().into(), NpcKind::StoneGolem => comp::golem::Body::random().into(),
NpcKind::Reddragon => comp::dragon::Body::random().into(), NpcKind::Reddragon => comp::dragon::Body::random().into(),
NpcKind::Crocodile => comp::quadruped_low::Body::random().into(), NpcKind::Crocodile => comp::quadruped_low::Body::random().into(),
NpcKind::Tarantula => comp::arthropod::Body::random().into(),
} }
} }
@ -303,6 +306,14 @@ impl NpcBody {
comp::quadruped_low::Body::random_with, comp::quadruped_low::Body::random_with,
) )
}) })
.or_else(|| {
parse(
s,
NpcKind::Tarantula,
&npc_names.arthropod,
comp::arthropod::Body::random_with,
)
})
.ok_or(()) .ok_or(())
} }
} }

View File

@ -2,7 +2,7 @@ use crate::{
astar::Astar, astar::Astar,
combat, combat,
comp::{ comp::{
biped_large, biped_small, arthropod, biped_large, biped_small,
character_state::OutputEvents, character_state::OutputEvents,
inventory::slot::{EquipSlot, Slot}, inventory::slot::{EquipSlot, Slot},
item::{Hands, ItemKind, Tool, ToolKind}, item::{Hands, ItemKind, Tool, ToolKind},
@ -129,6 +129,7 @@ impl Body {
quadruped_low::Species::Deadwood => 140.0, quadruped_low::Species::Deadwood => 140.0,
}, },
Body::Ship(_) => 0.0, Body::Ship(_) => 0.0,
Body::Arthropod(_) => 135.0,
} }
} }
@ -186,6 +187,7 @@ impl Body {
}, },
Body::Ship(ship) if ship.has_water_thrust() => 0.1, Body::Ship(ship) if ship.has_water_thrust() => 0.1,
Body::Ship(_) => 0.035, Body::Ship(_) => 0.035,
Body::Arthropod(_) => 3.5,
} }
} }
@ -214,6 +216,7 @@ impl Body {
Body::QuadrupedSmall(_) => Some(300.0 * self.mass().0), Body::QuadrupedSmall(_) => Some(300.0 * self.mass().0),
Body::Ship(ship) if ship.has_water_thrust() => Some(3500.0 * self.mass().0), Body::Ship(ship) if ship.has_water_thrust() => Some(3500.0 * self.mass().0),
Body::Ship(_) => None, Body::Ship(_) => None,
Body::Arthropod(_) => Some(300.0 * self.mass().0),
} }
} }
@ -242,6 +245,7 @@ impl Body {
| theropod::Species::Woodraptor => Some(0.4 * self.mass().0), | theropod::Species::Woodraptor => Some(0.4 * self.mass().0),
_ => None, _ => None,
}, },
Body::QuadrupedMedium(_) => Some(3.0 * self.mass().0),
_ => Some(0.4 * self.mass().0), _ => Some(0.4 * self.mass().0),
} }
.map(|f| f * GRAVITY) .map(|f| f * GRAVITY)

View File

@ -1692,6 +1692,7 @@ impl<'a> AgentData<'a> {
"Quad Low Quick" => Tactic::QuadLowQuick, "Quad Low Quick" => Tactic::QuadLowQuick,
"Quad Low Basic" => Tactic::QuadLowBasic, "Quad Low Basic" => Tactic::QuadLowBasic,
"Theropod Basic" | "Theropod Bird" => Tactic::Theropod, "Theropod Basic" | "Theropod Bird" => Tactic::Theropod,
"Arthropod Basic" => Tactic::Arthropod,
"Theropod Charge" => Tactic::CircleCharge { "Theropod Charge" => Tactic::CircleCharge {
radius: 6, radius: 6,
circle_time: 1, circle_time: 1,
@ -1968,6 +1969,9 @@ impl<'a> AgentData<'a> {
Tactic::Theropod => { Tactic::Theropod => {
self.handle_theropod_attack(agent, controller, &attack_data, tgt_data, read_data) self.handle_theropod_attack(agent, controller, &attack_data, tgt_data, read_data)
}, },
Tactic::Arthropod => {
self.handle_arthropod_attack(agent, controller, &attack_data, tgt_data, read_data)
},
Tactic::Turret => { Tactic::Turret => {
self.handle_turret_attack(agent, controller, &attack_data, tgt_data, read_data) self.handle_turret_attack(agent, controller, &attack_data, tgt_data, read_data)
}, },

View File

@ -0,0 +1,70 @@
use super::{
super::{vek::*, Animation},
ArthropodSkeleton, SkeletonAttr,
};
use common::states::utils::StageSection;
pub struct AlphaAnimation;
impl Animation for AlphaAnimation {
type Dependency<'a> = (f32, f32, Option<StageSection>, f32);
type Skeleton = ArthropodSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"arthropod_alpha\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_alpha")]
fn update_skeleton_inner<'a>(
skeleton: &Self::Skeleton,
(_velocity, global_time, stage_section, timer): Self::Dependency<'a>,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let (movement1base, movement2base, movement3) = match stage_section {
Some(StageSection::Buildup) => (anim_time.powi(2), 0.0, 0.0),
Some(StageSection::Swing) => (1.0, anim_time.powi(4), 0.0),
Some(StageSection::Recover) => (1.0, 1.0, anim_time),
_ => (0.0, 0.0, 0.0),
};
let pullback = 1.0 - movement3;
let subtract = global_time - timer;
let check = subtract - subtract.trunc();
let mirror = (check - 0.5).signum();
let movement1 = mirror * movement1base * pullback;
let movement2 = mirror * movement2base * pullback;
let movement1abs = movement1base * pullback;
let movement2abs = movement2base * pullback;
next.chest.scale = Vec3::one() / s_a.scaler;
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1);
next.mandible_l.position = Vec3::new(-s_a.mandible_l.0, s_a.mandible_l.1, s_a.mandible_l.2);
next.mandible_r.position = Vec3::new(s_a.mandible_r.0, s_a.mandible_r.1, s_a.mandible_r.2);
next.wing_fl.position = Vec3::new(-s_a.wing_fl.0, s_a.wing_fl.1, s_a.wing_fl.2);
next.wing_fr.position = Vec3::new(s_a.wing_fr.0, s_a.wing_fr.1, s_a.wing_fr.2);
next.wing_bl.position = Vec3::new(-s_a.wing_bl.0, s_a.wing_bl.1, s_a.wing_bl.2);
next.wing_br.position = Vec3::new(s_a.wing_br.0, s_a.wing_br.1, s_a.wing_br.2);
next.leg_fl.position = Vec3::new(-s_a.leg_fl.0, s_a.leg_fl.1, s_a.leg_fl.2);
next.leg_fr.position = Vec3::new(s_a.leg_fr.0, s_a.leg_fr.1, s_a.leg_fr.2);
next.leg_fcl.position = Vec3::new(-s_a.leg_fcl.0, s_a.leg_fcl.1, s_a.leg_fcl.2);
next.leg_fcr.position = Vec3::new(s_a.leg_fcr.0, s_a.leg_fcr.1, s_a.leg_fcr.2);
next.leg_bcl.position = Vec3::new(-s_a.leg_bcl.0, s_a.leg_bcl.1, s_a.leg_bcl.2);
next.leg_bcr.position = Vec3::new(s_a.leg_bcr.0, s_a.leg_bcr.1, s_a.leg_bcr.2);
next.leg_bl.position = Vec3::new(-s_a.leg_bl.0, s_a.leg_bl.1, s_a.leg_bl.2);
next.leg_br.position = Vec3::new(s_a.leg_br.0, s_a.leg_br.1, s_a.leg_br.2);
next
}
}

View File

@ -0,0 +1,54 @@
use super::{super::Animation, ArthropodSkeleton, SkeletonAttr};
//use std::{f32::consts::PI, ops::Mul};
use super::super::vek::*;
use std::ops::Mul;
pub struct IdleAnimation;
impl Animation for IdleAnimation {
type Dependency<'a> = f32;
type Skeleton = ArthropodSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"arthropod_idle\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_idle")]
fn update_skeleton_inner<'a>(
skeleton: &Self::Skeleton,
global_time: Self::Dependency<'a>,
anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.chest.scale = Vec3::one() / s_a.scaler;
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1);
next.mandible_l.position = Vec3::new(-s_a.mandible_l.0, s_a.mandible_l.1, s_a.mandible_l.2);
next.mandible_r.position = Vec3::new(s_a.mandible_r.0, s_a.mandible_r.1, s_a.mandible_r.2);
next.wing_fl.position = Vec3::new(-s_a.wing_fl.0, s_a.wing_fl.1, s_a.wing_fl.2);
next.wing_fr.position = Vec3::new(s_a.wing_fr.0, s_a.wing_fr.1, s_a.wing_fr.2);
next.wing_bl.position = Vec3::new(-s_a.wing_bl.0, s_a.wing_bl.1, s_a.wing_bl.2);
next.wing_br.position = Vec3::new(s_a.wing_br.0, s_a.wing_br.1, s_a.wing_br.2);
next.leg_fl.position = Vec3::new(-s_a.leg_fl.0, s_a.leg_fl.1, s_a.leg_fl.2);
next.leg_fr.position = Vec3::new(s_a.leg_fr.0, s_a.leg_fr.1, s_a.leg_fr.2);
next.leg_fcl.position = Vec3::new(-s_a.leg_fcl.0, s_a.leg_fcl.1, s_a.leg_fcl.2);
next.leg_fcr.position = Vec3::new(s_a.leg_fcr.0, s_a.leg_fcr.1, s_a.leg_fcr.2);
next.leg_bcl.position = Vec3::new(-s_a.leg_bcl.0, s_a.leg_bcl.1, s_a.leg_bcl.2);
next.leg_bcr.position = Vec3::new(s_a.leg_bcr.0, s_a.leg_bcr.1, s_a.leg_bcr.2);
next.leg_bl.position = Vec3::new(-s_a.leg_bl.0, s_a.leg_bl.1, s_a.leg_bl.2);
next.leg_br.position = Vec3::new(s_a.leg_br.0, s_a.leg_br.1, s_a.leg_br.2);
next
}
}

View File

@ -0,0 +1,53 @@
use super::{super::Animation, ArthropodSkeleton, SkeletonAttr};
//use std::f32::consts::PI;
use super::super::vek::*;
pub struct JumpAnimation;
impl Animation for JumpAnimation {
type Dependency<'a> = (f32, Vec3<f32>, Vec3<f32>, f32, Vec3<f32>);
type Skeleton = ArthropodSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"arthropod_jump\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_jump")]
fn update_skeleton_inner<'a>(
skeleton: &Self::Skeleton,
(_velocity, _orientation, _last_ori, _global_time, _avg_vel): Self::Dependency<'a>,
_anim_time: f32,
_rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
next.chest.scale = Vec3::one() / s_a.scaler;
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1);
next.mandible_l.position = Vec3::new(-s_a.mandible_l.0, s_a.mandible_l.1, s_a.mandible_l.2);
next.mandible_r.position = Vec3::new(s_a.mandible_r.0, s_a.mandible_r.1, s_a.mandible_r.2);
next.wing_fl.position = Vec3::new(-s_a.wing_fl.0, s_a.wing_fl.1, s_a.wing_fl.2);
next.wing_fr.position = Vec3::new(s_a.wing_fr.0, s_a.wing_fr.1, s_a.wing_fr.2);
next.wing_bl.position = Vec3::new(-s_a.wing_bl.0, s_a.wing_bl.1, s_a.wing_bl.2);
next.wing_br.position = Vec3::new(s_a.wing_br.0, s_a.wing_br.1, s_a.wing_br.2);
next.leg_fl.position = Vec3::new(-s_a.leg_fl.0, s_a.leg_fl.1, s_a.leg_fl.2);
next.leg_fr.position = Vec3::new(s_a.leg_fr.0, s_a.leg_fr.1, s_a.leg_fr.2);
next.leg_fcl.position = Vec3::new(-s_a.leg_fcl.0, s_a.leg_fcl.1, s_a.leg_fcl.2);
next.leg_fcr.position = Vec3::new(s_a.leg_fcr.0, s_a.leg_fcr.1, s_a.leg_fcr.2);
next.leg_bcl.position = Vec3::new(-s_a.leg_bcl.0, s_a.leg_bcl.1, s_a.leg_bcl.2);
next.leg_bcr.position = Vec3::new(s_a.leg_bcr.0, s_a.leg_bcr.1, s_a.leg_bcr.2);
next.leg_bl.position = Vec3::new(-s_a.leg_bl.0, s_a.leg_bl.1, s_a.leg_bl.2);
next.leg_br.position = Vec3::new(s_a.leg_br.0, s_a.leg_br.1, s_a.leg_br.2);
next
}
}

View File

@ -0,0 +1,232 @@
pub mod alpha;
pub mod idle;
pub mod jump;
pub mod run;
// Reexports
pub use self::{
alpha::AlphaAnimation, idle::IdleAnimation, jump::JumpAnimation, run::RunAnimation,
};
use super::{make_bone, vek::*, FigureBoneData, Offsets, Skeleton};
use common::comp::{self};
use core::convert::TryFrom;
pub type Body = comp::arthropod::Body;
skeleton_impls!(struct ArthropodSkeleton {
+ head,
+ chest,
+ mandible_l,
+ mandible_r,
+ wing_fl,
+ wing_fr,
+ wing_bl,
+ wing_br,
+ leg_fl,
+ leg_fr,
+ leg_fcl,
+ leg_fcr,
+ leg_bcl,
+ leg_bcr,
+ leg_bl,
+ leg_br,
});
impl Skeleton for ArthropodSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
const BONE_COUNT: usize = 16;
#[cfg(feature = "use-dyn-lib")]
const COMPUTE_FN: &'static [u8] = b"arthropod_compute_s\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_compute_s")]
fn compute_matrices_inner(
&self,
base_mat: Mat4<f32>,
buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
body: Self::Body,
) -> Offsets {
let chest_mat = base_mat * Mat4::<f32>::from(self.chest);
let head_mat = chest_mat * Mat4::<f32>::from(self.head);
let mandible_l_mat = head_mat * Mat4::<f32>::from(self.mandible_l);
let mandible_r_mat = head_mat * Mat4::<f32>::from(self.mandible_r);
let wing_fl_mat = chest_mat * Mat4::<f32>::from(self.wing_fl);
let wing_fr_mat = chest_mat * Mat4::<f32>::from(self.wing_fr);
let wing_bl_mat = chest_mat * Mat4::<f32>::from(self.wing_bl);
let wing_br_mat = chest_mat * Mat4::<f32>::from(self.wing_br);
let leg_fl_mat = chest_mat * Mat4::<f32>::from(self.leg_fl);
let leg_fr_mat = chest_mat * Mat4::<f32>::from(self.leg_fr);
let leg_fcl_mat = chest_mat * Mat4::<f32>::from(self.leg_fcl);
let leg_fcr_mat = chest_mat * Mat4::<f32>::from(self.leg_fcr);
let leg_bcl_mat = chest_mat * Mat4::<f32>::from(self.leg_bcl);
let leg_bcr_mat = chest_mat * Mat4::<f32>::from(self.leg_bcr);
let leg_bl_mat = chest_mat * Mat4::<f32>::from(self.leg_bl);
let leg_br_mat = chest_mat * Mat4::<f32>::from(self.leg_br);
*(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
make_bone(head_mat),
make_bone(chest_mat),
make_bone(mandible_l_mat),
make_bone(mandible_r_mat),
make_bone(wing_fl_mat),
make_bone(wing_fr_mat),
make_bone(wing_bl_mat),
make_bone(wing_br_mat),
make_bone(leg_fl_mat),
make_bone(leg_fr_mat),
make_bone(leg_fcl_mat),
make_bone(leg_fcr_mat),
make_bone(leg_bcl_mat),
make_bone(leg_bcr_mat),
make_bone(leg_bl_mat),
make_bone(leg_br_mat),
];
use comp::arthropod::Species::*;
let (mount_bone_mat, mount_bone_ori) = match (body.species, body.body_type) {
_ => (chest_mat, self.chest.orientation),
};
// Offset from the mounted bone's origin.
// Note: This could be its own bone if we need to animate it independently.
let mount_position = (mount_bone_mat * Vec4::from_point(mount_point(&body)))
.homogenized()
.xyz();
// NOTE: We apply the ori from base_mat externally so we don't need to worry
// about it here for now.
let mount_orientation = mount_bone_ori;
Offsets {
lantern: None,
mount_bone: Transform {
position: mount_position,
orientation: mount_orientation,
scale: Vec3::one(),
},
}
}
}
pub struct SkeletonAttr {
head: (f32, f32),
chest: (f32, f32),
mandible_l: (f32, f32, f32),
mandible_r: (f32, f32, f32),
wing_fl: (f32, f32, f32),
wing_fr: (f32, f32, f32),
wing_bl: (f32, f32, f32),
wing_br: (f32, f32, f32),
leg_fl: (f32, f32, f32),
leg_fr: (f32, f32, f32),
leg_fcl: (f32, f32, f32),
leg_fcr: (f32, f32, f32),
leg_bcl: (f32, f32, f32),
leg_bcr: (f32, f32, f32),
leg_bl: (f32, f32, f32),
leg_br: (f32, f32, f32),
scaler: f32,
}
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
type Error = ();
fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
match body {
comp::Body::Arthropod(body) => Ok(SkeletonAttr::from(body)),
_ => Err(()),
}
}
}
impl Default for SkeletonAttr {
fn default() -> Self {
Self {
head: (0.0, 0.0),
chest: (0.0, 0.0),
mandible_l: (0.0, 0.0, 0.0),
mandible_r: (0.0, 0.0, 0.0),
wing_fl: (0.0, 0.0, 0.0),
wing_fr: (0.0, 0.0, 0.0),
wing_bl: (0.0, 0.0, 0.0),
wing_br: (0.0, 0.0, 0.0),
leg_fl: (0.0, 0.0, 0.0),
leg_fr: (0.0, 0.0, 0.0),
leg_fcl: (0.0, 0.0, 0.0),
leg_fcr: (0.0, 0.0, 0.0),
leg_bcl: (0.0, 0.0, 0.0),
leg_bcr: (0.0, 0.0, 0.0),
leg_bl: (0.0, 0.0, 0.0),
leg_br: (0.0, 0.0, 0.0),
scaler: 0.0,
}
}
}
impl<'a> From<&'a Body> for SkeletonAttr {
fn from(body: &'a Body) -> Self {
use comp::arthropod::Species::*;
Self {
head: match (body.species, body.body_type) {
(Tarantula, _) => (8.0, 4.0),
},
chest: match (body.species, body.body_type) {
(Tarantula, _) => (1.0, -7.0),
},
mandible_l: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, 0.0, -4.0),
},
mandible_r: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, 0.0, -4.0),
},
wing_fl: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, 0.0, -4.0),
},
wing_fr: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, 0.0, -4.0),
},
wing_bl: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, 0.0, -4.0),
},
wing_br: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, 0.0, -4.0),
},
leg_fl: match (body.species, body.body_type) {
(Tarantula, _) => (2.5, -3.0, -4.0),
},
leg_fr: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, -0.5, -7.0),
},
leg_fcl: match (body.species, body.body_type) {
(Tarantula, _) => (2.5, -3.0, -4.0),
},
leg_fcr: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, -0.5, -7.0),
},
leg_bcl: match (body.species, body.body_type) {
(Tarantula, _) => (2.5, -3.0, -4.0),
},
leg_bcr: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, -0.5, -7.0),
},
leg_bl: match (body.species, body.body_type) {
(Tarantula, _) => (2.5, -3.0, -4.0),
},
leg_br: match (body.species, body.body_type) {
(Tarantula, _) => (3.0, -0.5, -7.0),
},
scaler: match (body.species, body.body_type) {
(Tarantula, _) => (1.0),
},
}
}
}
fn mount_point(body: &Body) -> Vec3<f32> {
use comp::arthropod::{BodyType::*, Species::*};
match (body.species, body.body_type) {
(_, _) => (0.0, -6.0, 6.0),
}
.into()
}

View File

@ -0,0 +1,94 @@
use super::{super::Animation, ArthropodSkeleton, SkeletonAttr};
//use std::{f32::consts::PI, ops::Mul};
use super::super::vek::*;
use std::f32::consts::{FRAC_PI_2, PI};
pub struct RunAnimation;
impl Animation for RunAnimation {
type Dependency<'a> = (Vec3<f32>, Vec3<f32>, Vec3<f32>, f32, Vec3<f32>, f32);
type Skeleton = ArthropodSkeleton;
#[cfg(feature = "use-dyn-lib")]
const UPDATE_FN: &'static [u8] = b"arthropod_run\0";
#[cfg_attr(feature = "be-dyn-lib", export_name = "arthropod_run")]
fn update_skeleton_inner<'a>(
skeleton: &Self::Skeleton,
(velocity, orientation, last_ori, _global_time, avg_vel, acc_vel): Self::Dependency<'a>,
anim_time: f32,
rate: &mut f32,
s_a: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let speed = (Vec2::<f32>::from(velocity).magnitude()).min(22.0);
*rate = 1.0;
//let speednorm = speed / 13.0;
let speednorm = (speed / 13.0).powf(0.25);
let mixed_vel = acc_vel + anim_time * 6.0; //sets run frequency using speed, with anim_time setting a floor
let speedmult = 1.0;
let lab: f32 = 0.6; //6
let short = ((1.0
/ (0.72
+ 0.28 * ((mixed_vel * 1.0 * lab * speedmult + PI * -0.15 - 0.5).sin()).powi(2)))
.sqrt())
* ((mixed_vel * 1.0 * lab * speedmult + PI * -0.15 - 0.5).sin())
* speednorm;
//
let shortalt = (mixed_vel * 1.0 * lab * speedmult + PI * 3.0 / 8.0 - 0.5).sin() * speednorm;
//FL
let foot1a = (mixed_vel * 1.0 * lab * speedmult + 0.0 + PI).sin() * speednorm; //1.5
let foot1b = (mixed_vel * 1.0 * lab * speedmult + FRAC_PI_2 + PI).sin() * speednorm; //1.9
//FR
let foot2a = (mixed_vel * 1.0 * lab * speedmult).sin() * speednorm; //1.2
let foot2b = (mixed_vel * 1.0 * lab * speedmult + FRAC_PI_2).sin() * speednorm; //1.6
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.2)
* last_ori.determine_side(Vec2::zero(), ori).signum()
} else {
0.0
} * 1.3;
let x_tilt = avg_vel.z.atan2(avg_vel.xy().magnitude()) * speednorm;
next.chest.scale = Vec3::one() / s_a.scaler;
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1);
next.chest.position = Vec3::new(0.0, s_a.chest.0, s_a.chest.1);
next.mandible_l.position = Vec3::new(-s_a.mandible_l.0, s_a.mandible_l.1, s_a.mandible_l.2);
next.mandible_r.position = Vec3::new(s_a.mandible_r.0, s_a.mandible_r.1, s_a.mandible_r.2);
next.wing_fl.position = Vec3::new(-s_a.wing_fl.0, s_a.wing_fl.1, s_a.wing_fl.2);
next.wing_fr.position = Vec3::new(s_a.wing_fr.0, s_a.wing_fr.1, s_a.wing_fr.2);
next.wing_bl.position = Vec3::new(-s_a.wing_bl.0, s_a.wing_bl.1, s_a.wing_bl.2);
next.wing_br.position = Vec3::new(s_a.wing_br.0, s_a.wing_br.1, s_a.wing_br.2);
next.leg_fl.position = Vec3::new(-s_a.leg_fl.0, s_a.leg_fl.1, s_a.leg_fl.2);
next.leg_fr.position = Vec3::new(s_a.leg_fr.0, s_a.leg_fr.1, s_a.leg_fr.2);
next.leg_fcl.position = Vec3::new(-s_a.leg_fcl.0, s_a.leg_fcl.1, s_a.leg_fcl.2);
next.leg_fcr.position = Vec3::new(s_a.leg_fcr.0, s_a.leg_fcr.1, s_a.leg_fcr.2);
next.leg_bcl.position = Vec3::new(-s_a.leg_bcl.0, s_a.leg_bcl.1, s_a.leg_bcl.2);
next.leg_bcr.position = Vec3::new(s_a.leg_bcr.0, s_a.leg_bcr.1, s_a.leg_bcr.2);
next.leg_bl.position = Vec3::new(-s_a.leg_bl.0, s_a.leg_bl.1, s_a.leg_bl.2);
next.leg_br.position = Vec3::new(s_a.leg_br.0, s_a.leg_br.1, s_a.leg_br.2);
next
}
}

View File

@ -47,6 +47,7 @@ macro_rules! skeleton_impls {
} }
} }
pub mod arthropod;
pub mod biped_large; pub mod biped_large;
pub mod biped_small; pub mod biped_small;
pub mod bird_large; pub mod bird_large;

View File

@ -716,6 +716,7 @@ fn body_species(body: &Body) -> String {
Body::Golem(body) => format!("{:?}", body.species), Body::Golem(body) => format!("{:?}", body.species),
Body::Theropod(body) => format!("{:?}", body.species), Body::Theropod(body) => format!("{:?}", body.species),
Body::QuadrupedLow(body) => format!("{:?}", body.species), Body::QuadrupedLow(body) => format!("{:?}", body.species),
Body::Arthropod(body) => format!("{:?}", body.species),
Body::Ship(body) => format!("{:?}", body), Body::Ship(body) => format!("{:?}", body),
} }
} }

View File

@ -2,6 +2,7 @@ use super::cache::{FigureKey, ToolKey};
use common::{ use common::{
assets::{self, AssetExt, AssetHandle, DotVoxAsset, ReloadWatcher, Ron}, assets::{self, AssetExt, AssetHandle, DotVoxAsset, ReloadWatcher, Ron},
comp::{ comp::{
arthropod::{self, BodyType as ABodyType, Species as ASpecies},
biped_large::{self, BodyType as BLBodyType, Species as BLSpecies}, biped_large::{self, BodyType as BLBodyType, Species as BLSpecies},
biped_small, biped_small,
bird_large::{self, BodyType as BLABodyType, Species as BLASpecies}, bird_large::{self, BodyType as BLABodyType, Species as BLASpecies},
@ -2151,6 +2152,384 @@ impl TheropodLateralSpec {
(lateral, Vec3::from(spec.foot_r.offset)) (lateral, Vec3::from(spec.foot_r.offset))
} }
} }
////
#[derive(Deserialize)]
struct ArthropodCentralSpec(HashMap<(ASpecies, ABodyType), SidedACentralVoxSpec>);
#[derive(Deserialize)]
struct SidedACentralVoxSpec {
head: ArthropodCentralSubSpec,
chest: ArthropodCentralSubSpec,
}
#[derive(Deserialize)]
struct ArthropodCentralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
central: VoxSimple,
}
#[derive(Deserialize)]
struct ArthropodLateralSpec(HashMap<(ASpecies, ABodyType), SidedALateralVoxSpec>);
#[derive(Deserialize)]
struct SidedALateralVoxSpec {
mandible_l: ArthropodLateralSubSpec,
mandible_r: ArthropodLateralSubSpec,
wing_fl: ArthropodLateralSubSpec,
wing_fr: ArthropodLateralSubSpec,
wing_bl: ArthropodLateralSubSpec,
wing_br: ArthropodLateralSubSpec,
leg_fl: ArthropodLateralSubSpec,
leg_fr: ArthropodLateralSubSpec,
leg_fcl: ArthropodLateralSubSpec,
leg_fcr: ArthropodLateralSubSpec,
leg_bcl: ArthropodLateralSubSpec,
leg_bcr: ArthropodLateralSubSpec,
leg_bl: ArthropodLateralSubSpec,
leg_br: ArthropodLateralSubSpec,
}
#[derive(Deserialize)]
struct ArthropodLateralSubSpec {
offset: [f32; 3], // Should be relative to initial origin
lateral: VoxSimple,
}
make_vox_spec!(
arthropod::Body,
struct ArthropodSpec {
central: ArthropodCentralSpec = "voxygen.voxel.Arthropod_central_manifest",
lateral: ArthropodLateralSpec = "voxygen.voxel.Arthropod_lateral_manifest",
},
|FigureKey { body, .. }, spec| {
[
Some(spec.central.read().0.mesh_head(
body.species,
body.body_type,
)),
Some(spec.central.read().0.mesh_chest(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_mandible_l(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_mandible_r(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_fl(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_fr(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_bl(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_wing_br(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_fl(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_fr(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_fcl(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_fcr(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_bcl(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_bcr(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_bl(
body.species,
body.body_type,
)),
Some(spec.lateral.read().0.mesh_leg_br(
body.species,
body.body_type,
)),
]
},
);
impl ArthropodCentralSpec {
fn mesh_head(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No head specification exists for the combination of {:?} and {:?}",
species, body_type
);
return load_mesh("not_found", Vec3::new(-5.0, -5.0, -2.5));
},
};
let central = graceful_load_segment(&spec.head.central.0);
(central, Vec3::from(spec.head.offset))
}
fn mesh_chest(&self, species: ASpecies, body_type: ABodyType) -> 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))
}
}
impl ArthropodLateralSpec {
fn mesh_mandible_l(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No left mandible 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_flipped(&spec.mandible_l.lateral.0, true);
(lateral, Vec3::from(spec.mandible_l.offset))
}
fn mesh_mandible_r(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No right mandible 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.mandible_r.lateral.0);
(lateral, Vec3::from(spec.mandible_r.offset))
}
fn mesh_wing_fl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No front left wing 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_flipped(&spec.wing_fl.lateral.0, true);
(lateral, Vec3::from(spec.wing_fl.offset))
}
fn mesh_wing_fr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No front right wing 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.wing_fr.lateral.0);
(lateral, Vec3::from(spec.wing_fr.offset))
}
fn mesh_wing_bl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No back left wing 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_flipped(&spec.wing_bl.lateral.0, true);
(lateral, Vec3::from(spec.wing_bl.offset))
}
fn mesh_wing_br(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No back right wing 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.wing_br.lateral.0);
(lateral, Vec3::from(spec.wing_br.offset))
}
fn mesh_leg_fl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No front left leg 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_flipped(&spec.leg_fl.lateral.0, true);
(lateral, Vec3::from(spec.leg_fl.offset))
}
fn mesh_leg_fr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No front right leg 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.leg_fr.lateral.0);
(lateral, Vec3::from(spec.leg_fr.offset))
}
fn mesh_leg_fcl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No front center left leg 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_flipped(&spec.leg_fcl.lateral.0, true);
(lateral, Vec3::from(spec.leg_fcl.offset))
}
fn mesh_leg_fcr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No front center right leg 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.leg_fcr.lateral.0);
(lateral, Vec3::from(spec.leg_fcr.offset))
}
fn mesh_leg_bcl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No back center left leg 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_flipped(&spec.leg_bcl.lateral.0, true);
(lateral, Vec3::from(spec.leg_bcl.offset))
}
fn mesh_leg_bcr(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No back center right leg 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.leg_bcr.lateral.0);
(lateral, Vec3::from(spec.leg_bcr.offset))
}
fn mesh_leg_bl(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No back left leg 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_flipped(&spec.leg_bl.lateral.0, true);
(lateral, Vec3::from(spec.leg_bl.offset))
}
fn mesh_leg_br(&self, species: ASpecies, body_type: ABodyType) -> BoneMeshes {
let spec = match self.0.get(&(species, body_type)) {
Some(spec) => spec,
None => {
error!(
"No back right leg 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.leg_br.lateral.0);
(lateral, Vec3::from(spec.leg_br.offset))
}
}
//// ////
#[derive(Deserialize)] #[derive(Deserialize)]
struct FishMediumCentralSpec(HashMap<(FMSpecies, FMBodyType), SidedFMCentralVoxSpec>); struct FishMediumCentralSpec(HashMap<(FMSpecies, FMBodyType), SidedFMCentralVoxSpec>);

View File

@ -21,7 +21,7 @@ use crate::{
}, },
}; };
use anim::{ use anim::{
biped_large::BipedLargeSkeleton, biped_small::BipedSmallSkeleton, arthropod::ArthropodSkeleton, biped_large::BipedLargeSkeleton, biped_small::BipedSmallSkeleton,
bird_large::BirdLargeSkeleton, bird_medium::BirdMediumSkeleton, character::CharacterSkeleton, bird_large::BirdLargeSkeleton, bird_medium::BirdMediumSkeleton, character::CharacterSkeleton,
dragon::DragonSkeleton, fish_medium::FishMediumSkeleton, fish_small::FishSmallSkeleton, dragon::DragonSkeleton, fish_medium::FishMediumSkeleton, fish_small::FishSmallSkeleton,
golem::GolemSkeleton, object::ObjectSkeleton, quadruped_low::QuadrupedLowSkeleton, golem::GolemSkeleton, object::ObjectSkeleton, quadruped_low::QuadrupedLowSkeleton,
@ -119,6 +119,7 @@ struct FigureMgrStates {
object_states: HashMap<EcsEntity, FigureState<ObjectSkeleton>>, object_states: HashMap<EcsEntity, FigureState<ObjectSkeleton>>,
ship_states: HashMap<EcsEntity, FigureState<ShipSkeleton>>, ship_states: HashMap<EcsEntity, FigureState<ShipSkeleton>>,
volume_states: HashMap<EcsEntity, FigureState<VolumeKey>>, volume_states: HashMap<EcsEntity, FigureState<VolumeKey>>,
arthropod_states: HashMap<EcsEntity, FigureState<ArthropodSkeleton>>,
} }
impl FigureMgrStates { impl FigureMgrStates {
@ -140,6 +141,7 @@ impl FigureMgrStates {
object_states: HashMap::new(), object_states: HashMap::new(),
ship_states: HashMap::new(), ship_states: HashMap::new(),
volume_states: HashMap::new(), volume_states: HashMap::new(),
arthropod_states: HashMap::new(),
} }
} }
@ -207,6 +209,10 @@ impl FigureMgrStates {
self.volume_states.get_mut(entity).map(DerefMut::deref_mut) self.volume_states.get_mut(entity).map(DerefMut::deref_mut)
} }
}, },
Body::Arthropod(_) => self
.arthropod_states
.get_mut(entity)
.map(DerefMut::deref_mut),
} }
} }
@ -237,6 +243,7 @@ impl FigureMgrStates {
self.volume_states.remove(entity).map(|e| e.meta) self.volume_states.remove(entity).map(|e| e.meta)
} }
}, },
Body::Arthropod(_) => self.arthropod_states.remove(entity).map(|e| e.meta),
} }
} }
@ -258,6 +265,7 @@ impl FigureMgrStates {
self.object_states.retain(|k, v| f(k, &mut *v)); self.object_states.retain(|k, v| f(k, &mut *v));
self.ship_states.retain(|k, v| f(k, &mut *v)); self.ship_states.retain(|k, v| f(k, &mut *v));
self.volume_states.retain(|k, v| f(k, &mut *v)); self.volume_states.retain(|k, v| f(k, &mut *v));
self.arthropod_states.retain(|k, v| f(k, &mut *v));
} }
fn count(&self) -> usize { fn count(&self) -> usize {
@ -278,6 +286,7 @@ impl FigureMgrStates {
+ self.object_states.len() + self.object_states.len()
+ self.ship_states.len() + self.ship_states.len()
+ self.volume_states.len() + self.volume_states.len()
+ self.arthropod_states.len()
} }
fn count_visible(&self) -> usize { fn count_visible(&self) -> usize {
@ -350,6 +359,11 @@ impl FigureMgrStates {
.iter() .iter()
.filter(|(_, c)| c.visible()) .filter(|(_, c)| c.visible())
.count() .count()
+ self
.arthropod_states
.iter()
.filter(|(_, c)| c.visible())
.count()
+ self.ship_states.iter().filter(|(_, c)| c.visible()).count() + self.ship_states.iter().filter(|(_, c)| c.visible()).count()
+ self + self
.volume_states .volume_states
@ -377,6 +391,7 @@ pub struct FigureMgr {
ship_model_cache: FigureModelCache<ShipSkeleton>, ship_model_cache: FigureModelCache<ShipSkeleton>,
golem_model_cache: FigureModelCache<GolemSkeleton>, golem_model_cache: FigureModelCache<GolemSkeleton>,
volume_model_cache: FigureModelCache<VolumeKey>, volume_model_cache: FigureModelCache<VolumeKey>,
arthropod_model_cache: FigureModelCache<ArthropodSkeleton>,
states: FigureMgrStates, states: FigureMgrStates,
} }
@ -400,6 +415,7 @@ impl FigureMgr {
ship_model_cache: FigureModelCache::new(), ship_model_cache: FigureModelCache::new(),
golem_model_cache: FigureModelCache::new(), golem_model_cache: FigureModelCache::new(),
volume_model_cache: FigureModelCache::new(), volume_model_cache: FigureModelCache::new(),
arthropod_model_cache: FigureModelCache::new(),
states: FigureMgrStates::default(), states: FigureMgrStates::default(),
} }
} }
@ -433,6 +449,7 @@ impl FigureMgr {
self.ship_model_cache.clean(&mut self.col_lights, tick); self.ship_model_cache.clean(&mut self.col_lights, tick);
self.golem_model_cache.clean(&mut self.col_lights, tick); self.golem_model_cache.clean(&mut self.col_lights, tick);
self.volume_model_cache.clean(&mut self.col_lights, tick); self.volume_model_cache.clean(&mut self.col_lights, tick);
self.arthropod_model_cache.clean(&mut self.col_lights, tick);
} }
pub fn update_lighting(&mut self, scene_data: &SceneData) { pub fn update_lighting(&mut self, scene_data: &SceneData) {
@ -3425,6 +3442,152 @@ impl FigureMgr {
body, body,
); );
}, },
Body::Arthropod(body) => {
let (model, skeleton_attr) = self.arthropod_model_cache.get_or_create_model(
renderer,
&mut self.col_lights,
body,
inventory,
tick,
player_camera_mode,
player_character_state,
&slow_jobs,
);
let state = self
.states
.arthropod_states
.entry(entity)
.or_insert_with(|| {
FigureState::new(renderer, ArthropodSkeleton::default(), body)
});
// Average velocity relative to the current ground
let rel_avg_vel = state.avg_vel - physics.ground_vel;
let (character, last_character) = match (character, last_character) {
(Some(c), Some(l)) => (c, l),
_ => continue,
};
if !character.same_variant(&last_character.0) {
state.state_time = 0.0;
}
let target_base = match (
physics.on_ground.is_some(),
rel_vel.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
physics.in_liquid().is_some(), // In water
) {
// Standing
(true, false, false) => anim::arthropod::IdleAnimation::update_skeleton(
&ArthropodSkeleton::default(),
time,
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// Running
(true, true, false) => anim::arthropod::RunAnimation::update_skeleton(
&ArthropodSkeleton::default(),
(
rel_vel,
// TODO: Update to use the quaternion.
ori * anim::vek::Vec3::<f32>::unit_y(),
state.last_ori * anim::vek::Vec3::<f32>::unit_y(),
time,
rel_avg_vel,
state.acc_vel,
),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
// In air
(false, _, false) => anim::arthropod::JumpAnimation::update_skeleton(
&ArthropodSkeleton::default(),
(
rel_vel.magnitude(),
// TODO: Update to use the quaternion.
ori * anim::vek::Vec3::<f32>::unit_y(),
state.last_ori * anim::vek::Vec3::<f32>::unit_y(),
time,
rel_avg_vel,
),
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
_ => anim::arthropod::IdleAnimation::update_skeleton(
&ArthropodSkeleton::default(),
time,
state.state_time,
&mut state_animation_rate,
skeleton_attr,
),
};
let target_bones = match &character {
CharacterState::ComboMelee(s) => {
let stage_index = (s.stage - 1) as usize;
let stage_time = s.timer.as_secs_f32();
let stage_progress =
if let Some(stage) = s.static_data.stage_data.get(stage_index) {
match s.stage_section {
StageSection::Buildup => {
stage_time / stage.base_buildup_duration.as_secs_f32()
},
StageSection::Swing => {
stage_time / stage.base_swing_duration.as_secs_f32()
},
StageSection::Recover => {
stage_time / stage.base_recover_duration.as_secs_f32()
},
_ => 0.0,
}
} else {
0.0
};
match s.stage {
1 => anim::arthropod::AlphaAnimation::update_skeleton(
&target_base,
(
rel_vel.magnitude(),
time,
Some(s.stage_section),
state.state_time,
),
stage_progress,
&mut state_animation_rate,
skeleton_attr,
),
_ => anim::arthropod::AlphaAnimation::update_skeleton(
&target_base,
(
rel_vel.magnitude(),
time,
Some(s.stage_section),
state.state_time,
),
stage_progress,
&mut state_animation_rate,
skeleton_attr,
),
}
},
// TODO!
_ => target_base,
};
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
state.update(
renderer,
&mut update_buf,
&common_params,
state_animation_rate,
model,
body,
);
},
Body::BirdLarge(body) => { Body::BirdLarge(body) => {
let (model, skeleton_attr) = self.bird_large_model_cache.get_or_create_model( let (model, skeleton_attr) = self.bird_large_model_cache.get_or_create_model(
renderer, renderer,
@ -5141,7 +5304,11 @@ impl FigureMgr {
object_model_cache, object_model_cache,
ship_model_cache, ship_model_cache,
golem_model_cache, golem_model_cache,
<<<<<<< HEAD
volume_model_cache, volume_model_cache,
=======
arthropod_model_cache,
>>>>>>> 9b36d29d2 (Adds arthropod skeleton)
states: states:
FigureMgrStates { FigureMgrStates {
character_states, character_states,
@ -5159,7 +5326,11 @@ impl FigureMgr {
golem_states, golem_states,
object_states, object_states,
ship_states, ship_states,
<<<<<<< HEAD
volume_states, volume_states,
=======
arthropod_states,
>>>>>>> 9b36d29d2 (Adds arthropod skeleton)
}, },
} = self; } = self;
let col_lights = &*col_lights_; let col_lights = &*col_lights_;
@ -5372,6 +5543,22 @@ impl FigureMgr {
), ),
) )
}), }),
Body::Arthropod(body) => arthropod_states
.get(&entity)
.filter(|state| filter_state(*state))
.map(move |state| {
(
state.bound(),
arthropod_model_cache.get_model(
col_lights,
body,
inventory,
tick,
player_camera_mode,
character_state,
),
)
}),
Body::Object(body) => object_states Body::Object(body) => object_states
.get(&entity) .get(&entity)
.filter(|state| filter_state(*state)) .filter(|state| filter_state(*state))