From df39bcb2dc81850e4d97684c183017a9129d785b Mon Sep 17 00:00:00 2001 From: jshipsey Date: Sun, 21 Apr 2019 13:35:43 -0400 Subject: [PATCH] velocity tilt Former-commit-id: 7373827734c9a65813537d7a1cb49b400c7d6fb8 --- voxygen/src/anim/character/idle.rs | 27 ++- voxygen/src/anim/character/mod.rs | 29 +-- voxygen/src/anim/character/run.rs | 51 +++-- voxygen/src/scene/figure.rs | 297 +++++++++++++++++++++++++++++ 4 files changed, 366 insertions(+), 38 deletions(-) diff --git a/voxygen/src/anim/character/idle.rs b/voxygen/src/anim/character/idle.rs index d6d48a5550..69f1ed5bfd 100644 --- a/voxygen/src/anim/character/idle.rs +++ b/voxygen/src/anim/character/idle.rs @@ -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 } } diff --git a/voxygen/src/anim/character/mod.rs b/voxygen/src/anim/character/mod.rs index 3d6e3e1dfc..f043977867 100644 --- a/voxygen/src/anim/character/mod.rs +++ b/voxygen/src/anim/character/mod.rs @@ -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); + } } diff --git a/voxygen/src/anim/character/run.rs b/voxygen/src/anim/character/run.rs index c5214bcb88..6ea0654d0f 100644 --- a/voxygen/src/anim/character/run.rs +++ b/voxygen/src/anim/character/run.rs @@ -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 } diff --git a/voxygen/src/scene/figure.rs b/voxygen/src/scene/figure.rs index 985e1746a0..bc4422e6ea 100644 --- a/voxygen/src/scene/figure.rs +++ b/voxygen/src/scene/figure.rs @@ -52,6 +52,105 @@ pub struct FigureCache { states: HashMap>, } +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, u64)>, + renderer: &mut Renderer, + tick: u64, + character: Character) + -> &'a (Model, 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, u64)>, + states: HashMap>, +} + 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) -> Mesh { + 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 { + Self::load_mesh(match head { + Head::DefaultHead => "head.vox", + }, Vec3::new(-5.5, -7.0, -6.0)) + } + + fn load_chest(chest: Chest) -> Mesh { + Self::load_mesh(match chest { + Chest::DefaultChest => "chest.vox", + }, Vec3::new(-2.5, -6.0, 0.0)) + } + + fn load_belt(belt: Belt) -> Mesh { + Self::load_mesh(match belt { + Belt::DefaultBelt => "belt.vox", + }, Vec3::new(-2.5, -5.0, 0.0)) + } + + fn load_pants(pants: Pants) -> Mesh { + Self::load_mesh(match pants { + Pants::DefaultPants => "pants.vox", + }, Vec3::new(-2.5, -5.0, 0.0)) + } + + fn load_left_hand(hand: Hand) -> Mesh { + Self::load_mesh(match hand { + Hand::DefaultHand => "hand.vox", + }, Vec3::new(0.0, -2.0, -7.0)) + } + + fn load_right_hand(hand: Hand) -> Mesh { + Self::load_mesh(match hand { + Hand::DefaultHand => "hand.vox", + }, Vec3::new(0.0, -2.0, -7.0)) + } + + fn load_left_foot(foot: Foot) -> Mesh { + Self::load_mesh(match foot { + Foot::DefaultFoot => "foot.vox", + }, Vec3::new(-3.5, -2.5, -8.0)) + } + + fn load_right_foot(foot: Foot) -> Mesh { + Self::load_mesh(match foot { + Foot::DefaultFoot => "foot.vox", + }, Vec3::new(-3.5, -2.5, -8.0)) + } + + fn load_weapon(weapon: Weapon) -> Mesh { + 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::(), + &ecs.read_storage::(), + &ecs.read_storage::(), + &ecs.read_storage::(), + ).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) { + let tick = client.get_tick(); + let ecs = client.state().ecs(); + let models = &mut self.models; + + for (entity, &character) in ( + &ecs.entities(), + &ecs.read_storage::(), + ).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 { + bone_consts: Consts, + locals: Consts, + skeleton: S, +} + +impl FigureState { + 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, dir: Vec3) { + let mat = + Mat4::::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()