From e39790e9e44dd32ba231a75d06ce9325657b7d15 Mon Sep 17 00:00:00 2001 From: Isse Date: Tue, 18 Apr 2023 15:40:34 +0200 Subject: [PATCH] make sprites work on multiple ships at once --- assets/common/manifests/ship_manifest.ron | 4 + assets/common/voxel/galleon/structure.vox | 4 +- common/src/comp/body/ship.rs | 2 +- voxygen/src/scene/figure/cache.rs | 15 +-- voxygen/src/scene/figure/mod.rs | 154 +++++++++++++--------- 5 files changed, 102 insertions(+), 77 deletions(-) diff --git a/assets/common/manifests/ship_manifest.ron b/assets/common/manifests/ship_manifest.ron index 4e753b8624..32e638397b 100644 --- a/assets/common/manifests/ship_manifest.ron +++ b/assets/common/manifests/ship_manifest.ron @@ -88,5 +88,9 @@ offset: (0.0, 0.0, 0.0), central: ("empty"), ), + + custom_indices: { + 1: Air(Helm, 0), + }, ), }) diff --git a/assets/common/voxel/galleon/structure.vox b/assets/common/voxel/galleon/structure.vox index 50be736ce1..5b2e466d25 100644 --- a/assets/common/voxel/galleon/structure.vox +++ b/assets/common/voxel/galleon/structure.vox @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b8ba947b5ac052bdc70c30350fde7b0a9926d39ecbd6bd945f02cef751c31ab -size 70193 +oid sha256:b4070cbfc78efc2e86520d0dcee5b0107a6c08e86914870503c6645575726a52 +size 37357 diff --git a/common/src/comp/body/ship.rs b/common/src/comp/body/ship.rs index 45f5c52e24..aa458c4547 100644 --- a/common/src/comp/body/ship.rs +++ b/common/src/comp/body/ship.rs @@ -100,7 +100,7 @@ impl Body { pub fn density(&self) -> Density { match self { Body::DefaultAirship | Body::AirBalloon | Body::Volume => Density(AIR_DENSITY), - _ => Density(AIR_DENSITY * 0.8 + WATER_DENSITY * 0.2), // Most boats should be buoyant + _ => Density(AIR_DENSITY * 0.2 + WATER_DENSITY * 0.8), // Most boats should be buoyant } } diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index efdc980b1e..03d27c02cc 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -8,7 +8,6 @@ use crate::{ segment::{generate_mesh_base_vol_figure, generate_mesh_base_vol_terrain}, }, render::{ - pipelines::terrain::{BoundLocals as BoundTerrainLocals, Locals as TerrainLocals}, BoneMeshes, ColLightInfo, FigureModel, Instances, Mesh, Renderer, SpriteInstance, TerrainVertex, }, @@ -621,8 +620,6 @@ where &'c mut self, renderer: &mut Renderer, col_lights: &mut super::FigureColLights, - pos: Vec3, - ori: Quaternion, body: Skel::Body, extra: ::Extra, tick: u64, @@ -664,8 +661,6 @@ where col_light, (opaque, bounds), vertex_range, - pos, - ori, sprite_instances, blocks_of_interest, blocks_offset, @@ -883,10 +878,9 @@ where pub fn get_sprites( &self, body: Skel::Body, - ) -> Option<( - &BoundTerrainLocals, + ) -> Option< &[Instances; SPRITE_LOD_LEVELS], - )> { + > { let key = FigureKey { body, item_key: None, @@ -897,13 +891,15 @@ where return None; }; - Some((&model.terrain_locals, &model.sprite_instances)) + Some(&model.sprite_instances) }) } + /* pub fn update_terrain_locals( &mut self, renderer: &mut Renderer, + entity: Entity, body: Skel::Body, pos: Vec3, ori: Quaternion, @@ -928,4 +924,5 @@ where )]) } } + */ } diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 65ed7f757e..782ff0a2c5 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -146,7 +146,6 @@ pub struct TerrainModelEntry { blocks_offset: Vec3, - terrain_locals: BoundTerrainLocals, sprite_instances: [Instances; SPRITE_LOD_LEVELS], blocks_of_interest: BlocksOfInterest, @@ -204,8 +203,8 @@ struct FigureMgrStates { golem_states: HashMap>, object_states: HashMap>, item_drop_states: HashMap>, - ship_states: HashMap>, - volume_states: HashMap>, + ship_states: HashMap>, + volume_states: HashMap>, arthropod_states: HashMap>, } @@ -330,10 +329,12 @@ impl FigureMgrStates { Body::Object(_) => self.object_states.remove(entity).map(|e| e.meta), Body::ItemDrop(_) => self.item_drop_states.remove(entity).map(|e| e.meta), Body::Ship(ship) => { - if ship.manifest_entry().is_some() { + if matches!(ship, ship::Body::Volume) { + self.volume_states.remove(entity).map(|e| e.meta) + } else if ship.manifest_entry().is_some() { self.ship_states.remove(entity).map(|e| e.meta) } else { - self.volume_states.remove(entity).map(|e| e.meta) + None } }, Body::Arthropod(_) => self.arthropod_states.remove(entity).map(|e| e.meta), @@ -471,6 +472,24 @@ impl FigureMgrStates { .filter(|(_, c)| c.visible()) .count() } + + fn get_terrain_locals<'a, Q: ?Sized>(&'a self, body: &Body, entity: &Q) -> Option<&'a BoundTerrainLocals> + where + EcsEntity: Borrow, + Q: Hash + Eq, { + match body { + Body::Ship(body) => { + if matches!(body, ship::Body::Volume) { + self.volume_states.get(entity).map(|state| &state.extra) + } else if body.manifest_entry().is_some() { + self.ship_states.get(entity).map(|state| &state.extra) + } else { + None + } + } + _ => None, + } + } } pub struct FigureMgr { @@ -6102,8 +6121,6 @@ impl FigureMgr { self.volume_model_cache.get_or_create_terrain_model( renderer, &mut self.col_lights, - pos.0.into(), - ori.into_vec4().into(), vk, Arc::clone(vol), tick, @@ -6126,20 +6143,11 @@ impl FigureMgr { model, vk, ); - - self.volume_model_cache.update_terrain_locals( - renderer, - vk, - pos.0.into(), - ori.into_vec4().into(), - ); continue; } else if body.manifest_entry().is_some() { self.ship_model_cache.get_or_create_terrain_model( renderer, &mut self.col_lights, - pos.0.into(), - ori.into_vec4().into(), body, (), tick, @@ -6218,13 +6226,6 @@ impl FigureMgr { model, body, ); - - self.ship_model_cache.update_terrain_locals( - renderer, - body, - pos.0.into(), - ori.into_vec4().into(), - ); }, } } @@ -6344,8 +6345,8 @@ impl FigureMgr { // Don't render dead entities .filter(|(_, _, _, _, health, _)| health.map_or(true, |h| !h.is_dead)) { - if let Some((data, sprite_instances)) = - self.get_sprite_instances(entity, body, collider) + if let Some((sprite_instances, data)) = + self.get_sprite_instances(entity, body, collider).zip(self.states.get_terrain_locals(body, &entity)) { let dist = collider .and_then(|collider| { @@ -6888,7 +6889,27 @@ impl FigureMgr { ) }), Body::Ship(body) => { - if body.manifest_entry().is_some() { + if matches!(body, ship::Body::Volume) { + volume_states + .get(&entity) + .filter(|state| filter_state(state)) + .map(move |state| { + ( + state.bound(), + volume_model_cache + .get_model( + col_lights, + VolumeKey { entity, mut_count }, + None, + tick, + CameraMode::default(), + None, + None, + ) + .map(ModelEntryRef::Terrain), + ) + }) + } else if body.manifest_entry().is_some() { ship_states .get(&entity) .filter(|state| filter_state(state)) @@ -6909,25 +6930,7 @@ impl FigureMgr { ) }) } else { - volume_states - .get(&entity) - .filter(|state| filter_state(state)) - .map(move |state| { - ( - state.bound(), - volume_model_cache - .get_model( - col_lights, - VolumeKey { entity, mut_count }, - None, - tick, - CameraMode::default(), - None, - None, - ) - .map(ModelEntryRef::Terrain), - ) - }) + None } }, } { @@ -6970,10 +6973,8 @@ impl FigureMgr { entity: EcsEntity, body: &Body, collider: Option<&Collider>, - ) -> Option<( - &'a BoundTerrainLocals, - &'a [Instances; SPRITE_LOD_LEVELS], - )> { + ) -> Option< + &'a [Instances; SPRITE_LOD_LEVELS]> { match body { Body::Ship(body) => { if let Some(Collider::Volume(vol)) = collider { @@ -6982,8 +6983,10 @@ impl FigureMgr { mut_count: vol.mut_count, }; self.volume_model_cache.get_sprites(vk) - } else { + } else if body.manifest_entry().is_some() { self.ship_model_cache.get_sprites(*body) + } else { + None } }, _ => None, @@ -7195,8 +7198,6 @@ impl FigureColLights { (tex, tex_size): ColLightInfo, (opaque, bounds): (Mesh, math::Aabb), vertex_ranges: [Range; N], - pos: Vec3, - ori: Quaternion, sprite_instances: [Vec; SPRITE_LOD_LEVELS], blocks_of_interest: BlocksOfInterest, blocks_offset: Vec3, @@ -7222,13 +7223,6 @@ impl FigureColLights { ); }); - let terrain_locals = renderer.create_terrain_bound_locals(&[TerrainLocals::new( - pos, - ori, - Vec2::zero(), - 0.0, - )]); - let sprite_instances = sprite_instances.map(|instances| renderer.create_instances(&instances)); @@ -7238,7 +7232,6 @@ impl FigureColLights { col_lights, lod_vertex_ranges: vertex_ranges, model: FigureModel { opaque: model }, - terrain_locals, sprite_instances, blocks_of_interest, blocks_offset, @@ -7320,18 +7313,19 @@ impl FigureStateMeta { } } -pub struct FigureState { +pub struct FigureState { meta: FigureStateMeta, skeleton: S, + extra: D, } -impl Deref for FigureState { +impl Deref for FigureState { type Target = FigureStateMeta; fn deref(&self) -> &Self::Target { &self.meta } } -impl DerefMut for FigureState { +impl DerefMut for FigureState { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.meta } } @@ -7358,7 +7352,35 @@ pub struct FigureUpdateCommonParameters<'a> { pub ground_vel: Vec3, } -impl FigureState { +pub trait FigureData: Sized { + fn new(renderer: &mut Renderer) -> Self; + + fn update(&mut self, renderer: &mut Renderer, parameters: &FigureUpdateCommonParameters); +} + +impl FigureData for () { + fn new(_renderer: &mut Renderer) -> Self { + () + } + + fn update(&mut self, _renderer: &mut Renderer, _parameters: &FigureUpdateCommonParameters) { + () + } +} + +impl FigureData for BoundTerrainLocals { + fn new(renderer: &mut Renderer) -> Self { + renderer.create_terrain_bound_locals(&[TerrainLocals::new(Vec3::zero(), Quaternion::identity(), Vec2::zero(), 0.0)]) + } + + fn update(&mut self, renderer: &mut Renderer, parameters: &FigureUpdateCommonParameters) { + renderer.update_consts(self, &[ + TerrainLocals::new(parameters.pos.into(), parameters.ori.into_vec4().into(), Vec2::zero(), 0.0), + ]) + } +} + +impl FigureState { pub fn new(renderer: &mut Renderer, skeleton: S, body: S::Body) -> Self { let mut buf = [Default::default(); anim::MAX_BONE_COUNT]; let offsets = @@ -7386,6 +7408,7 @@ impl FigureState { bound: renderer.create_figure_bound_locals(&[FigureLocals::default()], bone_consts), }, skeleton, + extra: D::new(renderer), } } @@ -7394,7 +7417,7 @@ impl FigureState { renderer: &mut Renderer, trail_mgr: Option<&mut TrailMgr>, buf: &mut [anim::FigureBoneData; anim::MAX_BONE_COUNT], - FigureUpdateCommonParameters { + parameters @ FigureUpdateCommonParameters { entity, pos, ori, @@ -7614,6 +7637,7 @@ impl FigureState { } else { self.acc_vel = 0.0; } + self.extra.update(renderer, parameters); } pub fn bound(&self) -> &pipelines::figure::BoundLocals { &self.bound }