diff --git a/voxygen/anim/src/arthropod/mod.rs b/voxygen/anim/src/arthropod/mod.rs index a0c25c2599..9761406f8f 100644 --- a/voxygen/anim/src/arthropod/mod.rs +++ b/voxygen/anim/src/arthropod/mod.rs @@ -113,6 +113,7 @@ impl Skeleton for ArthropodSkeleton { orientation: mount_orientation, scale: Vec3::one(), }, + trail_points: None, } } } diff --git a/voxygen/anim/src/biped_large/mod.rs b/voxygen/anim/src/biped_large/mod.rs index 76f7a3cefb..293c9b702a 100644 --- a/voxygen/anim/src/biped_large/mod.rs +++ b/voxygen/anim/src/biped_large/mod.rs @@ -137,6 +137,7 @@ impl Skeleton for BipedLargeSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/biped_small/mod.rs b/voxygen/anim/src/biped_small/mod.rs index d1704bbf77..85f818dc5a 100644 --- a/voxygen/anim/src/biped_small/mod.rs +++ b/voxygen/anim/src/biped_small/mod.rs @@ -83,6 +83,7 @@ impl Skeleton for BipedSmallSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/bird_large/mod.rs b/voxygen/anim/src/bird_large/mod.rs index fd6b6198f0..5f868b5572 100644 --- a/voxygen/anim/src/bird_large/mod.rs +++ b/voxygen/anim/src/bird_large/mod.rs @@ -106,6 +106,7 @@ impl Skeleton for BirdLargeSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/bird_medium/mod.rs b/voxygen/anim/src/bird_medium/mod.rs index dab98a6819..e5596d3754 100644 --- a/voxygen/anim/src/bird_medium/mod.rs +++ b/voxygen/anim/src/bird_medium/mod.rs @@ -60,6 +60,7 @@ impl Skeleton for BirdMediumSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/character/mod.rs b/voxygen/anim/src/character/mod.rs index db7a935e65..4cbfb8401c 100644 --- a/voxygen/anim/src/character/mod.rs +++ b/voxygen/anim/src/character/mod.rs @@ -125,6 +125,7 @@ impl Skeleton for CharacterSkeleton { } else { shorts_mat } * Mat4::::from(self.lantern); + let main_mat = control_l_mat * Mat4::::from(self.main); *(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [ make_bone(head_mat), @@ -139,7 +140,7 @@ impl Skeleton for CharacterSkeleton { make_bone(chest_mat * Mat4::::from(self.shoulder_l)), make_bone(chest_mat * Mat4::::from(self.shoulder_r)), make_bone(chest_mat * Mat4::::from(self.glider)), - make_bone(control_l_mat * Mat4::::from(self.main)), + make_bone(main_mat), make_bone(control_r_mat * Mat4::::from(self.second)), make_bone(lantern_mat), // FIXME: Should this be control_l_mat? @@ -155,6 +156,10 @@ impl Skeleton for CharacterSkeleton { .into(), ..Default::default() }, + trail_points: Some(( + (main_mat * Vec4::new(0.0, 0.5, -6.0, 1.0)).xyz(), + (main_mat * Vec4::new(0.0, 0.5, -6.0, 1.0)).xyz(), + )), } } } diff --git a/voxygen/anim/src/dragon/mod.rs b/voxygen/anim/src/dragon/mod.rs index 7b82a7cc6a..27a41bff4c 100644 --- a/voxygen/anim/src/dragon/mod.rs +++ b/voxygen/anim/src/dragon/mod.rs @@ -81,6 +81,7 @@ impl Skeleton for DragonSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/fish_medium/mod.rs b/voxygen/anim/src/fish_medium/mod.rs index 80685b7ea3..cd073a2eff 100644 --- a/voxygen/anim/src/fish_medium/mod.rs +++ b/voxygen/anim/src/fish_medium/mod.rs @@ -60,6 +60,7 @@ impl Skeleton for FishMediumSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/fish_small/mod.rs b/voxygen/anim/src/fish_small/mod.rs index a24dca196c..c3242e683b 100644 --- a/voxygen/anim/src/fish_small/mod.rs +++ b/voxygen/anim/src/fish_small/mod.rs @@ -51,6 +51,7 @@ impl Skeleton for FishSmallSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/fixture/mod.rs b/voxygen/anim/src/fixture/mod.rs index aa5b3e85fd..d16a09f59d 100644 --- a/voxygen/anim/src/fixture/mod.rs +++ b/voxygen/anim/src/fixture/mod.rs @@ -37,6 +37,7 @@ impl Skeleton for FixtureSkeleton { Offsets { lantern: None, mount_bone: Transform::default(), + trail_points: None, } } } diff --git a/voxygen/anim/src/golem/mod.rs b/voxygen/anim/src/golem/mod.rs index 4f3391f88b..03c1e67569 100644 --- a/voxygen/anim/src/golem/mod.rs +++ b/voxygen/anim/src/golem/mod.rs @@ -83,6 +83,7 @@ impl Skeleton for GolemSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/lib.rs b/voxygen/anim/src/lib.rs index 0f9e54c801..9ad1f37475 100644 --- a/voxygen/anim/src/lib.rs +++ b/voxygen/anim/src/lib.rs @@ -103,6 +103,7 @@ pub fn init() { lazy_static::initialize(&LIB); } pub struct Offsets { pub lantern: Option>, pub mount_bone: Transform, + pub trail_points: Option<(Vec3, Vec3)>, } pub trait Skeleton: Send + Sync + 'static { diff --git a/voxygen/anim/src/object/mod.rs b/voxygen/anim/src/object/mod.rs index 7d4cbbb2aa..3617386913 100644 --- a/voxygen/anim/src/object/mod.rs +++ b/voxygen/anim/src/object/mod.rs @@ -49,6 +49,7 @@ impl Skeleton for ObjectSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/quadruped_low/mod.rs b/voxygen/anim/src/quadruped_low/mod.rs index 66a70fec99..3e9abf6269 100644 --- a/voxygen/anim/src/quadruped_low/mod.rs +++ b/voxygen/anim/src/quadruped_low/mod.rs @@ -97,6 +97,7 @@ impl Skeleton for QuadrupedLowSkeleton { orientation: mount_orientation, scale: Vec3::one(), }, + trail_points: None, } } } diff --git a/voxygen/anim/src/quadruped_medium/mod.rs b/voxygen/anim/src/quadruped_medium/mod.rs index a55e58b6e2..2494790ba2 100644 --- a/voxygen/anim/src/quadruped_medium/mod.rs +++ b/voxygen/anim/src/quadruped_medium/mod.rs @@ -109,6 +109,7 @@ impl Skeleton for QuadrupedMediumSkeleton { orientation: mount_orientation, scale: Vec3::one(), }, + trail_points: None, } } } diff --git a/voxygen/anim/src/quadruped_small/mod.rs b/voxygen/anim/src/quadruped_small/mod.rs index fb9e21ffec..d11a7aa3c0 100644 --- a/voxygen/anim/src/quadruped_small/mod.rs +++ b/voxygen/anim/src/quadruped_small/mod.rs @@ -74,6 +74,7 @@ impl Skeleton for QuadrupedSmallSkeleton { orientation: mount_orientation, scale: Vec3::one(), }, + trail_points: None, } } } diff --git a/voxygen/anim/src/ship/mod.rs b/voxygen/anim/src/ship/mod.rs index 9c02b67178..9d2378bd21 100644 --- a/voxygen/anim/src/ship/mod.rs +++ b/voxygen/anim/src/ship/mod.rs @@ -53,6 +53,7 @@ impl Skeleton for ShipSkeleton { ), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/anim/src/theropod/mod.rs b/voxygen/anim/src/theropod/mod.rs index 21db915f25..8d7bc70c8f 100644 --- a/voxygen/anim/src/theropod/mod.rs +++ b/voxygen/anim/src/theropod/mod.rs @@ -84,6 +84,7 @@ impl Skeleton for TheropodSkeleton { .into(), ..Default::default() }, + trail_points: None, } } } diff --git a/voxygen/src/lib.rs b/voxygen/src/lib.rs index bd54371f29..4b51c032fb 100644 --- a/voxygen/src/lib.rs +++ b/voxygen/src/lib.rs @@ -9,7 +9,8 @@ drain_filter, once_cell, trait_alias, - option_get_or_insert_default + option_get_or_insert_default, + map_try_insert )] #![recursion_limit = "2048"] diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index ea0689c14e..2e7bba6769 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -9,15 +9,15 @@ pub use volume::VolumeKey; use crate::{ ecs::comp::Interpolated, render::{ - pipelines::{self, ColLights}, + pipelines::{self, trail, ColLights}, ColLightInfo, FigureBoneData, FigureDrawer, FigureLocals, FigureModel, FigureShadowDrawer, - Mesh, RenderError, Renderer, SubModel, TerrainVertex, + Mesh, Quad, RenderError, Renderer, SubModel, TerrainVertex, }, scene::{ camera::{Camera, CameraMode, Dependents}, math, terrain::Terrain, - SceneData, + SceneData, TrailMgr, }, }; use anim::{ @@ -571,6 +571,7 @@ impl FigureMgr { pub fn maintain( &mut self, renderer: &mut Renderer, + trail_mgr: &TrailMgr, scene_data: &SceneData, // Visible chunk data. visible_psr_bounds: math::Aabr, @@ -855,6 +856,7 @@ impl FigureMgr { let body = *body; let common_params = FigureUpdateCommonParameters { + entity: Some(entity), pos: pos.0, ori, scale, @@ -1759,6 +1761,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -1958,6 +1961,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -2274,6 +2278,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -2631,6 +2636,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -2734,6 +2740,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -2816,6 +2823,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_base, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -3342,6 +3350,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -3428,6 +3437,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_base, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -3606,6 +3616,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -3897,6 +3908,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -4219,6 +4231,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -4301,6 +4314,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_base, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -4922,6 +4936,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -5162,6 +5177,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -5289,6 +5305,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -5385,6 +5402,7 @@ impl FigureMgr { state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -5478,6 +5496,7 @@ impl FigureMgr { state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp); state.update( renderer, + Some(trail_mgr), &mut update_buf, &common_params, state_animation_rate, @@ -6170,6 +6189,7 @@ impl FigureColLights { pub struct FigureStateMeta { lantern_offset: Option>, + trail_points: Option<(anim::vek::Vec3, anim::vek::Vec3)>, // Animation to be applied to rider of this entity mount_transform: anim::vek::Transform, // Contains the position of this figure or if it is a rider it will contain the mount's @@ -6218,6 +6238,7 @@ impl DerefMut for FigureState { /// Parameters that don't depend on the body variant or animation results and /// are also not mutable pub struct FigureUpdateCommonParameters<'a> { + pub entity: Option, pub pos: anim::vek::Vec3, pub ori: anim::vek::Quaternion, pub scale: f32, @@ -6245,6 +6266,7 @@ impl FigureState { Self { meta: FigureStateMeta { lantern_offset: offsets.lantern, + trail_points: offsets.trail_points, mount_transform: offsets.mount_bone, mount_world_pos: anim::vek::Vec3::zero(), state_time: 0.0, @@ -6266,8 +6288,10 @@ impl FigureState { pub fn update( &mut self, renderer: &mut Renderer, + trail_mgr: Option<&TrailMgr>, buf: &mut [anim::FigureBoneData; anim::MAX_BONE_COUNT], FigureUpdateCommonParameters { + entity, pos, ori, scale, @@ -6410,6 +6434,26 @@ impl FigureState { renderer.update_consts(&mut self.meta.bound.1, &new_bone_consts[0..S::BONE_COUNT]); self.lantern_offset = offsets.lantern; + // Handle weapon trails + if let Some(trail_mgr) = trail_mgr { + if let Some(dynamic_model) = entity + .as_ref() + .and_then(|e| trail_mgr.dynamic_models.get(e)) + { + if let (Some((p1, p2)), Some((p3, p4))) = (self.trail_points, offsets.trail_points) + { + let vertex = |p: anim::vek::Vec3| trail::Vertex { + pos: p.into_array(), + }; + let mut quad_mesh = Mesh::new(); + // TODO: Figure out how to get + quad_mesh.push_quad(Quad::new(vertex(p1), vertex(p2), vertex(p3), vertex(p4))); + renderer.update_model(dynamic_model, &quad_mesh, trail_mgr.offset * 4); + } + } + } + self.trail_points = offsets.trail_points; + // TODO: compute the mount bone only when it is needed self.mount_transform = offsets.mount_bone; self.mount_world_pos = mount_transform_pos.map_or(*pos, |(_, pos)| pos); diff --git a/voxygen/src/scene/figure/volume.rs b/voxygen/src/scene/figure/volume.rs index 92f1ced12b..c6e423af03 100644 --- a/voxygen/src/scene/figure/volume.rs +++ b/voxygen/src/scene/figure/volume.rs @@ -49,6 +49,7 @@ impl anim::Skeleton for VolumeKey { anim::Offsets { lantern: None, mount_bone: anim::vek::Transform::default(), + trail_points: None, } } diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index fdc49c2343..32cff66092 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -698,6 +698,7 @@ impl Scene { // Maintain the figures. let _figure_bounds = self.figure_mgr.maintain( renderer, + &self.trail_mgr, scene_data, visible_psr_bounds, &self.camera, diff --git a/voxygen/src/scene/simple.rs b/voxygen/src/scene/simple.rs index f6fc3b6d28..c01c0b3609 100644 --- a/voxygen/src/scene/simple.rs +++ b/voxygen/src/scene/simple.rs @@ -148,6 +148,7 @@ impl Scene { .create_figure(renderer, greedy.finalize(), (opaque_mesh, bounds), [range]); let mut buf = [Default::default(); anim::MAX_BONE_COUNT]; let common_params = FigureUpdateCommonParameters { + entity: None, pos: anim::vek::Vec3::zero(), ori: anim::vek::Quaternion::rotation_from_to_3d( anim::vek::Vec3::unit_y(), @@ -165,7 +166,15 @@ impl Scene { terrain: None, ground_vel: Vec3::zero(), }; - state.update(renderer, &mut buf, &common_params, 1.0, Some(&model), ()); + state.update( + renderer, + None, + &mut buf, + &common_params, + 1.0, + Some(&model), + (), + ); (model, state) }), col_lights, @@ -330,6 +339,7 @@ impl Scene { .0; let mut buf = [Default::default(); anim::MAX_BONE_COUNT]; let common_params = FigureUpdateCommonParameters { + entity: None, pos: anim::vek::Vec3::zero(), ori: anim::vek::Quaternion::rotation_from_to_3d( anim::vek::Vec3::unit_y(), @@ -348,7 +358,7 @@ impl Scene { ground_vel: Vec3::zero(), }; - figure_state.update(renderer, &mut buf, &common_params, 1.0, model, body); + figure_state.update(renderer, None, &mut buf, &common_params, 1.0, model, body); } } diff --git a/voxygen/src/scene/trail.rs b/voxygen/src/scene/trail.rs index 6217a2991a..bf49ab654e 100644 --- a/voxygen/src/scene/trail.rs +++ b/voxygen/src/scene/trail.rs @@ -1,23 +1,64 @@ use super::SceneData; use crate::render::{DynamicModel, Renderer, TrailDrawer, TrailVertex}; -use common::uid::Uid; +use common::comp::CharacterState; use common_base::span; +use specs::{Entity as EcsEntity, Join, WorldExt}; use std::collections::HashMap; +// use vek::*; pub struct TrailMgr { + /// Keep track of lifetimes + // trails: Vec, + /// GPU vertex buffers - dynamic_models: HashMap>, + pub dynamic_models: HashMap>, + + /// Offset + pub offset: usize, } +const TRAIL_DYNAMIC_MODEL_SIZE: usize = 60; + impl TrailMgr { pub fn new(_renderer: &mut Renderer) -> Self { Self { + // trails: Vec::new(), dynamic_models: HashMap::new(), + offset: 0, } } - pub fn maintain(&mut self, _renderer: &mut Renderer, _scene_data: &SceneData) { + pub fn maintain(&mut self, renderer: &mut Renderer, scene_data: &SceneData) { span!(_guard, "maintain", "TrailMgr::maintain"); + + if scene_data.particles_enabled { + // remove dead Trails + // self.trails + // .retain(|t| t.alive_until > scene_data.state.get_time()); + + // Update offset + self.offset = (self.offset + 1) % TRAIL_DYNAMIC_MODEL_SIZE; + + // Update dynamic models + let ecs = scene_data.state.ecs(); + for (entity, _char_state) in + (&ecs.entities(), &ecs.read_storage::()).join() + { + let _ = self.dynamic_models.try_insert( + entity, + renderer.create_dynamic_model(TRAIL_DYNAMIC_MODEL_SIZE * 4), + ); + } + + // Clear dynamic models for entities that no longer exist (is this even + // necessary? not sure if this growing too big is a concern) + self.dynamic_models + .retain(|entity, _| ecs.entities().is_alive(*entity)) + } else { + // if !self.trails.is_empty() { + // self.trails.clear(); + // } + } } pub fn render<'a>(&'a self, drawer: &mut TrailDrawer<'_, 'a>, scene_data: &SceneData) { @@ -29,3 +70,22 @@ impl TrailMgr { } } } + +// struct Trail { +// entity: EcsEntity, +// pos1: Vec3, +// pos2: Vec3, +// alive_until: f64, +// } + +// impl Trail { +// pub fn new(entity: EcsEntity, pos1: Vec3, pos2: Vec3, time: +// f64) -> Self { const LIFETIME: f64 = 1.0; +// Self { +// entity, +// pos1, +// pos2, +// alive_until: time + LIFETIME, +// } +// } +// }