velocity tilt

Former-commit-id: 7373827734c9a65813537d7a1cb49b400c7d6fb8
This commit is contained in:
jshipsey 2019-04-21 13:35:43 -04:00
parent f85e3546cf
commit df39bcb2dc
4 changed files with 366 additions and 38 deletions

View File

@ -32,32 +32,41 @@ impl Animation for IdleAnimation {
let waveultracos_slow = (time as f32 * 1.0 + PI).cos();
let wave_dip = (wave_slow.abs() - 0.5).abs();
next.head.offset = Vec3::new(0.0, 0.0, 12.0 + waveultra_slow * 0.4) / SCALE;
next.head.offset = Vec3::new(-1.0, 0.0, 12.0 + waveultra_slow * 0.4) / SCALE;
next.head.ori = Quaternion::rotation_y(waveultra_slow * 0.05);
next.head.scale = Vec3::one() / SCALE;
next.chest.offset = Vec3::new(0.0, 0.0, 8.0 + waveultra_slow * 0.4) / SCALE;
next.chest.offset = Vec3::new(2.5, 0.0, 8.0 + waveultra_slow * 0.4) / SCALE;
next.chest.ori = Quaternion::rotation_y(0.0);
next.chest.scale = Vec3::one() / SCALE;
next.belt.offset = Vec3::new(0.0, 0.0, 6.0 + waveultra_slow * 0.4) / SCALE;
next.belt.offset = Vec3::new(2.5, 0.0, 6.0 + waveultra_slow * 0.4) / SCALE;
next.belt.ori = Quaternion::rotation_y(0.0);
next.belt.scale = Vec3::one() / SCALE;
next.shorts.offset = Vec3::new(0.0, 0.0, 3.0 + waveultra_slow * 0.4) / SCALE;
next.shorts.offset = Vec3::new(2.5, 0.0, 3.0 + waveultra_slow * 0.4) / SCALE;
next.shorts.ori = Quaternion::rotation_y(0.0);
next.shorts.scale = Vec3::one() / SCALE;
next.l_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3, 7.5, 11.0 + waveultra_slow * 1.1) / SCALE;
next.l_hand.offset = Vec3::new(2.0 + waveultracos_slow * 0.3, 7.5, 13.5 + waveultra_slow * 1.1) / SCALE;
next.l_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06);
next.r_hand.offset = Vec3::new(0.0 + waveultracos_slow * 0.3 , - 7.5, 11.0 + waveultra_slow * 1.1) / SCALE;
next.r_hand.offset = Vec3::new(2.0 + waveultracos_slow * 0.3 , - 7.5, 13.5 + waveultra_slow * 1.1) / SCALE;
next.r_hand.ori = Quaternion::rotation_y(0.0 + waveultra_slow * 0.06);
next.l_foot.offset = Vec3::new(2.5, 3.4, 6.0) / SCALE;
next.l_foot.offset = Vec3::new(5.0, 3.4, 8.0) / SCALE;
next.l_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04);
next.r_foot.offset = Vec3::new(2.5, -3.4, 6.0) / SCALE;
next.r_foot.offset = Vec3::new(5.0, -3.4, 8.0) / SCALE;
next.r_foot.ori = Quaternion::rotation_y(0.04 + waveultra_slow * 0.04);
next.back.offset = Vec3::new(-6.5, 16.0, 15.0);
next.back.offset = Vec3::new(-4.5, 12.0, 11.0);
next.back.ori = Quaternion::rotation_x(2.5);
next.back.scale = Vec3::one();
next.torso.offset = Vec3::new(0.0, 0.0, 0.0);
next.torso.ori = Quaternion::rotation_y(0.0);
next.torso.scale = Vec3::one();
next
}
}

View File

@ -27,6 +27,8 @@ pub struct CharacterSkeleton {
l_foot: Bone,
r_foot: Bone,
back: Bone,
torso: Bone,
}
impl CharacterSkeleton {
@ -41,6 +43,8 @@ impl CharacterSkeleton {
l_foot: Bone::default(),
r_foot: Bone::default(),
back: Bone::default(),
torso: Bone::default(),
}
}
}
@ -48,24 +52,25 @@ impl CharacterSkeleton {
impl Skeleton for CharacterSkeleton {
fn compute_matrices(&self) -> [FigureBoneData; 16] {
let chest_mat = self.chest.compute_base_matrix();
let torso_mat = self.torso.compute_base_matrix();
[
FigureBoneData::new(self.head.compute_base_matrix()),
FigureBoneData::new(chest_mat),
FigureBoneData::new(self.belt.compute_base_matrix()),
FigureBoneData::new(self.shorts.compute_base_matrix()),
FigureBoneData::new(self.l_hand.compute_base_matrix()),
FigureBoneData::new(self.r_hand.compute_base_matrix()),
FigureBoneData::new(self.l_foot.compute_base_matrix()),
FigureBoneData::new(self.r_foot.compute_base_matrix()),
FigureBoneData::new(chest_mat * self.back.compute_base_matrix()),
FigureBoneData::default(),
FigureBoneData::new(torso_mat * self.head.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat),
FigureBoneData::new(torso_mat * self.belt.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.shorts.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.l_hand.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.r_hand.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.l_foot.compute_base_matrix()),
FigureBoneData::new(torso_mat * self.r_foot.compute_base_matrix()),
FigureBoneData::new(torso_mat * chest_mat * self.back.compute_base_matrix()),
FigureBoneData::new(torso_mat),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
FigureBoneData::default(),
]
}
@ -79,5 +84,7 @@ impl Skeleton for CharacterSkeleton {
self.l_foot.interpolate(&target.l_foot);
self.r_foot.interpolate(&target.r_foot);
self.back.interpolate(&target.back);
self.torso.interpolate(&target.torso);
}
}

View File

@ -23,39 +23,54 @@ impl Animation for RunAnimation {
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (time as f32 * 14.0).sin();
let wave = (time as f32 * 16.0).sin();
let wavetest = (wave.cbrt());
let fuzzwave = (time as f32 * 12.0).sin();
let wavecos = (time as f32 * 14.0).cos();
let wavecos = (time as f32 * 16.0).cos();
let wave_slow = (time as f32 * 8.0 + PI).sin();
let wavecos_slow = (time as f32 * 8.0 + PI).cos();
let wave_dip = (wave_slow.abs() - 0.5).abs();
next.head.offset = Vec3::unit_z() * (12.0 + fuzzwave *1.0)/ SCALE;
next.chest.offset = Vec3::unit_z() * (8.0 + fuzzwave * 0.8) / SCALE;
next.chest.ori = Quaternion::rotation_z(wave * 0.3);
next.head.offset = Vec3::unit_z() * (12.0 + wave *1.3)/ SCALE;
next.chest.scale = Vec3::one() * 1.0;
next.belt.offset = Vec3::unit_z() * (6.0 + fuzzwave * 0.8) / SCALE;
next.belt.ori = Quaternion::rotation_z(wave * 0.3);
next.chest.offset = Vec3::new(2.5, 0.0, 8.0 + wave * 1.1) / SCALE;
next.chest.ori = Quaternion::rotation_z(wavecos * 0.2);
next.chest.scale = Vec3::one() / SCALE;
next.shorts.offset = Vec3::unit_z() * (3.0 + fuzzwave * 0.8) / SCALE;
next.shorts.ori = Quaternion::rotation_z(wave * 0.2);
next.belt.offset = Vec3::new(2.5, 0.0, 6.0 + wave * 1.1) / SCALE;
next.belt.ori = Quaternion::rotation_z(wavecos * 0.2);
next.belt.scale = Vec3::one() /SCALE;
next.l_hand.offset = Vec3::new(0.0 - wavecos * 1.0, 7.5, 11.0 - wave * 1.0) / SCALE;
next.l_hand.ori = Quaternion::rotation_y(wave * -1.8);
next.r_hand.offset = Vec3::new(0.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / SCALE;
next.r_hand.ori = Quaternion::rotation_y(wave * 1.8);
next.shorts.offset = Vec3::new(2.5, 0.0, 3.0 + wave * 1.1) / SCALE;
next.shorts.ori = Quaternion::rotation_z(wavecos * 0.6);
next.shorts.scale = Vec3::one() /SCALE;
next.l_foot.offset = Vec3::new(2.5 - wavecos * 4.0, 3.4, 6.0 + wave * 2.9) / SCALE;
next.l_foot.ori = Quaternion::rotation_y(wave * -1.0);
next.r_foot.offset = Vec3::new(2.5 + wavecos * 4.0, -3.4, 6.0 - wave * 2.9) / SCALE;
next.l_hand.offset = Vec3::new(2.0 - wavecos * 1.0, 7.5, 11.0 - wave * 1.0) / SCALE;
next.l_hand.ori = Quaternion::rotation_y(wavecos * -1.8);
next.r_hand.offset = Vec3::new(2.0 + wavecos * 1.0, -7.5, 11.0 + wave * 1.0) / SCALE;
next.r_hand.ori = Quaternion::rotation_y(wavecos * 1.8);
next.r_foot.ori = Quaternion::rotation_y(wave * 1.0);
next.l_foot.offset = Vec3::new(3.5 - wave * 1.0, 3.4, 6.0) / SCALE;
next.l_foot.ori = Quaternion::rotation_y(-0.0 + wave * 1.5);
next.l_foot.scale = Vec3::one() / SCALE;
next.back.offset = Vec3::new(-6.0, 16.0, 15.0);
next.r_foot.offset = Vec3::new(3.5 + wave * 1.0, -3.4, 6.0) / SCALE;
next.r_foot.ori = Quaternion::rotation_y(-0.0 - wave * 1.5);
next.back.offset = Vec3::new(-4.5, 12.0, 11.0);
next.back.ori = Quaternion::rotation_x(2.5);
next.back.scale = Vec3::one();
next.torso.offset = Vec3::new(0.0, 0.0, 0.0);
next.torso.ori = Quaternion::rotation_y(0.2 + wave * 0.1);
next.torso.scale = Vec3::one();
next
}

View File

@ -52,6 +52,105 @@ pub struct FigureCache {
states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
}
impl FigureCache {
pub fn new() -> Self {
Self {
models: HashMap::new(),
states: HashMap::new(),
}
}
<<<<<<< HEAD
pub fn get_or_create_model<'a>(
models: &'a mut HashMap<Character, (Model<FigurePipeline>, u64)>,
renderer: &mut Renderer,
tick: u64,
character: Character)
-> &'a (Model<FigurePipeline>, u64) {
match models.get_mut(&character) {
Some((model, last_used)) => {
*last_used = tick;
}
None => {
models.insert(character, ({
let bone_meshes = [
Some(Self::load_head(character.head)),
Some(Self::load_chest(character.chest)),
Some(Self::load_belt(character.belt)),
Some(Self::load_pants(character.pants)),
Some(Self::load_left_hand(character.hand)),
Some(Self::load_right_hand(character.hand)),
Some(Self::load_left_foot(character.foot)),
Some(Self::load_right_foot(character.foot)),
Some(Self::load_weapon(character.weapon)),
None,
None,
None,
None,
None,
None,
None,
];
=======
let bone_meshes = [
Some(load_segment("head.vox").generate_mesh(Vec3::new(1.0, -7.0, -6.0))),
Some(load_segment("chest.vox").generate_mesh(Vec3::new(-2.5, -6.0, 0.0))),
use std::{
collections::HashMap,
f32,
};
use specs::{Entity as EcsEntity, Component, VecStorage, Join};
use vek::*;
use client::Client;
use common::{
comp::{
self,
character::{
Character,
Head,
Chest,
Belt,
Pants,
Hand,
Foot,
Weapon,
}
},
figure::Segment,
msg,
assets,
};
use crate::{
Error,
render::{
Consts,
Globals,
Mesh,
Model,
Renderer,
FigurePipeline,
FigureBoneData,
FigureLocals,
},
anim::{
Animation,
Skeleton,
character::{
CharacterSkeleton,
RunAnimation,
IdleAnimation,
},
},
mesh::Meshable,
};
pub struct FigureCache {
models: HashMap<Character, (Model<FigurePipeline>, u64)>,
states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
}
impl FigureCache {
pub fn new() -> Self {
Self {
@ -91,6 +190,204 @@ impl FigureCache {
None,
];
let mut mesh = Mesh::new();
bone_meshes
.iter()
.enumerate()
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
.for_each(|(i, bone_mesh)| {
mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8))
});
let mut mesh = Mesh::new();
bone_meshes
.iter()
.enumerate()
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
.for_each(|(i, bone_mesh)| {
mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8))
});
renderer.create_model(&mesh).unwrap()
}, tick));
}
}
&models[&character]
}
pub fn clean(&mut self, tick: u64) {
// TODO: Don't hard-code this
self.models.retain(|_, (_, last_used)| *last_used + 60 > tick);
}
fn load_mesh(filename: &'static str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
let fullpath: String = ["/voxygen/voxel/", filename].concat();
Segment::from(dot_vox::load_bytes(
assets::load(fullpath.as_str())
.expect("Error loading file")
.as_slice(),
).unwrap())
.generate_mesh(position)
}
fn load_head(head: Head) -> Mesh<FigurePipeline> {
Self::load_mesh(match head {
Head::DefaultHead => "head.vox",
}, Vec3::new(-5.5, -7.0, -6.0))
}
fn load_chest(chest: Chest) -> Mesh<FigurePipeline> {
Self::load_mesh(match chest {
Chest::DefaultChest => "chest.vox",
}, Vec3::new(-2.5, -6.0, 0.0))
}
fn load_belt(belt: Belt) -> Mesh<FigurePipeline> {
Self::load_mesh(match belt {
Belt::DefaultBelt => "belt.vox",
}, Vec3::new(-2.5, -5.0, 0.0))
}
fn load_pants(pants: Pants) -> Mesh<FigurePipeline> {
Self::load_mesh(match pants {
Pants::DefaultPants => "pants.vox",
}, Vec3::new(-2.5, -5.0, 0.0))
}
fn load_left_hand(hand: Hand) -> Mesh<FigurePipeline> {
Self::load_mesh(match hand {
Hand::DefaultHand => "hand.vox",
}, Vec3::new(0.0, -2.0, -7.0))
}
fn load_right_hand(hand: Hand) -> Mesh<FigurePipeline> {
Self::load_mesh(match hand {
Hand::DefaultHand => "hand.vox",
}, Vec3::new(0.0, -2.0, -7.0))
}
fn load_left_foot(foot: Foot) -> Mesh<FigurePipeline> {
Self::load_mesh(match foot {
Foot::DefaultFoot => "foot.vox",
}, Vec3::new(-3.5, -2.5, -8.0))
}
fn load_right_foot(foot: Foot) -> Mesh<FigurePipeline> {
Self::load_mesh(match foot {
Foot::DefaultFoot => "foot.vox",
}, Vec3::new(-3.5, -2.5, -8.0))
}
fn load_weapon(weapon: Weapon) -> Mesh<FigurePipeline> {
Self::load_mesh(match weapon {
Weapon::Sword => "sword.vox",
// TODO actually match against other weapons and set the right model
_ => "sword.vox",
}, Vec3::new(0.0, 0.0, -4.0))
}
pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) {
let time = client.state().get_time();
let ecs = client.state_mut().ecs_mut();
for (entity, pos, dir, character, animation_history) in (
&ecs.entities(),
&ecs.read_storage::<comp::phys::Pos>(),
&ecs.read_storage::<comp::phys::Dir>(),
&ecs.read_storage::<comp::Character>(),
&ecs.read_storage::<comp::AnimationHistory>(),
).join() {
let state = self.states
.entry(entity)
.or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new()));
let target_skeleton = match animation_history.current {
comp::character::Animation::Idle => IdleAnimation::update_skeleton(&mut state.skeleton, time),
comp::character::Animation::Run => RunAnimation::update_skeleton(&mut state.skeleton, time),
};
state.skeleton.interpolate(&target_skeleton);
state.update(renderer, pos.0, dir.0);
}
self.states.retain(|entity, _| ecs.entities().is_alive(*entity));
}
pub fn render(&mut self, renderer: &mut Renderer, client: &mut Client, globals: &Consts<Globals>) {
let tick = client.get_tick();
let ecs = client.state().ecs();
let models = &mut self.models;
for (entity, &character) in (
&ecs.entities(),
&ecs.read_storage::<comp::Character>(),
).join() {
let model = Self::get_or_create_model(models, renderer, tick, character);
let state = self.states.get(&entity).unwrap();
renderer.render_figure(
&model.0,
globals,
&state.locals,
&state.bone_consts,
);
}
}
}
pub struct FigureState<S: Skeleton> {
bone_consts: Consts<FigureBoneData>,
locals: Consts<FigureLocals>,
skeleton: S,
}
impl<S: Skeleton> FigureState<S> {
pub fn new(renderer: &mut Renderer, skeleton: S) -> Self {
Self {
bone_consts: renderer.create_consts(&skeleton.compute_matrices()).unwrap(),
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(),
skeleton,
}
}
fn update(&mut self, renderer: &mut Renderer, pos: Vec3<f32>, dir: Vec3<f32>) {
let mat =
Mat4::<f32>::identity() *
Mat4::translation_3d(pos) *
Mat4::rotation_z(dir.y.atan2(dir.x));// + f32//::consts)::PI / 2.0);
let locals = FigureLocals::new(mat);
renderer.update_consts(&mut self.locals, &[locals]).unwrap();
renderer.update_consts(&mut self.bone_consts, &self.skeleton.compute_matrices()).unwrap();
}
}
Some(load_segment("pants.vox").generate_mesh(Vec3::new(-2.5, -5.0, 0.0))),
Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -8.0))),
Some(load_segment("hand.vox").generate_mesh(Vec3::new(0.0, -2.0, -8.0))),
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-3.5, -2.5, -8.0))),
Some(load_segment("foot.vox").generate_mesh(Vec3::new(-3.5, -2.5, -8.0))),
Some(load_segment("sword.vox").generate_mesh(Vec3::new(0.0, -0.0, -4.0))),
None,
None,
None,
None,
None,
None,
None,
];
let mut mesh = Mesh::new();
bone_meshes
.iter()
.enumerate()
.filter_map(|(i, bm)| bm.as_ref().map(|bm| (i, bm)))
.for_each(|(i, bone_mesh)| {
mesh.push_mesh_map(bone_mesh, |vert| vert.with_bone_idx(i as u8))
});
>>>>>>> velocity tilt
let mut mesh = Mesh::new();
bone_meshes
.iter()