make sprites work on multiple ships at once

This commit is contained in:
Isse 2023-04-18 15:40:34 +02:00
parent 134d0f0c04
commit e39790e9e4
5 changed files with 102 additions and 77 deletions

View File

@ -88,5 +88,9 @@
offset: (0.0, 0.0, 0.0), offset: (0.0, 0.0, 0.0),
central: ("empty"), central: ("empty"),
), ),
custom_indices: {
1: Air(Helm, 0),
},
), ),
}) })

BIN
assets/common/voxel/galleon/structure.vox (Stored with Git LFS)

Binary file not shown.

View File

@ -100,7 +100,7 @@ impl Body {
pub fn density(&self) -> Density { pub fn density(&self) -> Density {
match self { match self {
Body::DefaultAirship | Body::AirBalloon | Body::Volume => Density(AIR_DENSITY), 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
} }
} }

View File

@ -8,7 +8,6 @@ use crate::{
segment::{generate_mesh_base_vol_figure, generate_mesh_base_vol_terrain}, segment::{generate_mesh_base_vol_figure, generate_mesh_base_vol_terrain},
}, },
render::{ render::{
pipelines::terrain::{BoundLocals as BoundTerrainLocals, Locals as TerrainLocals},
BoneMeshes, ColLightInfo, FigureModel, Instances, Mesh, Renderer, SpriteInstance, BoneMeshes, ColLightInfo, FigureModel, Instances, Mesh, Renderer, SpriteInstance,
TerrainVertex, TerrainVertex,
}, },
@ -621,8 +620,6 @@ where
&'c mut self, &'c mut self,
renderer: &mut Renderer, renderer: &mut Renderer,
col_lights: &mut super::FigureColLights, col_lights: &mut super::FigureColLights,
pos: Vec3<f32>,
ori: Quaternion<f32>,
body: Skel::Body, body: Skel::Body,
extra: <Skel::Body as BodySpec>::Extra, extra: <Skel::Body as BodySpec>::Extra,
tick: u64, tick: u64,
@ -664,8 +661,6 @@ where
col_light, col_light,
(opaque, bounds), (opaque, bounds),
vertex_range, vertex_range,
pos,
ori,
sprite_instances, sprite_instances,
blocks_of_interest, blocks_of_interest,
blocks_offset, blocks_offset,
@ -883,10 +878,9 @@ where
pub fn get_sprites( pub fn get_sprites(
&self, &self,
body: Skel::Body, body: Skel::Body,
) -> Option<( ) -> Option<
&BoundTerrainLocals,
&[Instances<SpriteInstance>; SPRITE_LOD_LEVELS], &[Instances<SpriteInstance>; SPRITE_LOD_LEVELS],
)> { > {
let key = FigureKey { let key = FigureKey {
body, body,
item_key: None, item_key: None,
@ -897,13 +891,15 @@ where
return None; return None;
}; };
Some((&model.terrain_locals, &model.sprite_instances)) Some(&model.sprite_instances)
}) })
} }
/*
pub fn update_terrain_locals( pub fn update_terrain_locals(
&mut self, &mut self,
renderer: &mut Renderer, renderer: &mut Renderer,
entity: Entity,
body: Skel::Body, body: Skel::Body,
pos: Vec3<f32>, pos: Vec3<f32>,
ori: Quaternion<f32>, ori: Quaternion<f32>,
@ -928,4 +924,5 @@ where
)]) )])
} }
} }
*/
} }

View File

@ -146,7 +146,6 @@ pub struct TerrainModelEntry<const N: usize> {
blocks_offset: Vec3<f32>, blocks_offset: Vec3<f32>,
terrain_locals: BoundTerrainLocals,
sprite_instances: [Instances<SpriteInstance>; SPRITE_LOD_LEVELS], sprite_instances: [Instances<SpriteInstance>; SPRITE_LOD_LEVELS],
blocks_of_interest: BlocksOfInterest, blocks_of_interest: BlocksOfInterest,
@ -204,8 +203,8 @@ struct FigureMgrStates {
golem_states: HashMap<EcsEntity, FigureState<GolemSkeleton>>, golem_states: HashMap<EcsEntity, FigureState<GolemSkeleton>>,
object_states: HashMap<EcsEntity, FigureState<ObjectSkeleton>>, object_states: HashMap<EcsEntity, FigureState<ObjectSkeleton>>,
item_drop_states: HashMap<EcsEntity, FigureState<ItemDropSkeleton>>, item_drop_states: HashMap<EcsEntity, FigureState<ItemDropSkeleton>>,
ship_states: HashMap<EcsEntity, FigureState<ShipSkeleton>>, ship_states: HashMap<EcsEntity, FigureState<ShipSkeleton, BoundTerrainLocals>>,
volume_states: HashMap<EcsEntity, FigureState<VolumeKey>>, volume_states: HashMap<EcsEntity, FigureState<VolumeKey, BoundTerrainLocals>>,
arthropod_states: HashMap<EcsEntity, FigureState<ArthropodSkeleton>>, arthropod_states: HashMap<EcsEntity, FigureState<ArthropodSkeleton>>,
} }
@ -330,10 +329,12 @@ impl FigureMgrStates {
Body::Object(_) => self.object_states.remove(entity).map(|e| e.meta), Body::Object(_) => self.object_states.remove(entity).map(|e| e.meta),
Body::ItemDrop(_) => self.item_drop_states.remove(entity).map(|e| e.meta), Body::ItemDrop(_) => self.item_drop_states.remove(entity).map(|e| e.meta),
Body::Ship(ship) => { 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) self.ship_states.remove(entity).map(|e| e.meta)
} else { } else {
self.volume_states.remove(entity).map(|e| e.meta) None
} }
}, },
Body::Arthropod(_) => self.arthropod_states.remove(entity).map(|e| e.meta), Body::Arthropod(_) => self.arthropod_states.remove(entity).map(|e| e.meta),
@ -471,6 +472,24 @@ impl FigureMgrStates {
.filter(|(_, c)| c.visible()) .filter(|(_, c)| c.visible())
.count() .count()
} }
fn get_terrain_locals<'a, Q: ?Sized>(&'a self, body: &Body, entity: &Q) -> Option<&'a BoundTerrainLocals>
where
EcsEntity: Borrow<Q>,
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 { pub struct FigureMgr {
@ -6102,8 +6121,6 @@ impl FigureMgr {
self.volume_model_cache.get_or_create_terrain_model( self.volume_model_cache.get_or_create_terrain_model(
renderer, renderer,
&mut self.col_lights, &mut self.col_lights,
pos.0.into(),
ori.into_vec4().into(),
vk, vk,
Arc::clone(vol), Arc::clone(vol),
tick, tick,
@ -6126,20 +6143,11 @@ impl FigureMgr {
model, model,
vk, vk,
); );
self.volume_model_cache.update_terrain_locals(
renderer,
vk,
pos.0.into(),
ori.into_vec4().into(),
);
continue; continue;
} else if body.manifest_entry().is_some() { } else if body.manifest_entry().is_some() {
self.ship_model_cache.get_or_create_terrain_model( self.ship_model_cache.get_or_create_terrain_model(
renderer, renderer,
&mut self.col_lights, &mut self.col_lights,
pos.0.into(),
ori.into_vec4().into(),
body, body,
(), (),
tick, tick,
@ -6218,13 +6226,6 @@ impl FigureMgr {
model, model,
body, 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 // Don't render dead entities
.filter(|(_, _, _, _, health, _)| health.map_or(true, |h| !h.is_dead)) .filter(|(_, _, _, _, health, _)| health.map_or(true, |h| !h.is_dead))
{ {
if let Some((data, sprite_instances)) = if let Some((sprite_instances, data)) =
self.get_sprite_instances(entity, body, collider) self.get_sprite_instances(entity, body, collider).zip(self.states.get_terrain_locals(body, &entity))
{ {
let dist = collider let dist = collider
.and_then(|collider| { .and_then(|collider| {
@ -6888,7 +6889,27 @@ impl FigureMgr {
) )
}), }),
Body::Ship(body) => { 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 ship_states
.get(&entity) .get(&entity)
.filter(|state| filter_state(state)) .filter(|state| filter_state(state))
@ -6909,25 +6930,7 @@ impl FigureMgr {
) )
}) })
} else { } else {
volume_states None
.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),
)
})
} }
}, },
} { } {
@ -6970,10 +6973,8 @@ impl FigureMgr {
entity: EcsEntity, entity: EcsEntity,
body: &Body, body: &Body,
collider: Option<&Collider>, collider: Option<&Collider>,
) -> Option<( ) -> Option<
&'a BoundTerrainLocals, &'a [Instances<SpriteInstance>; SPRITE_LOD_LEVELS]> {
&'a [Instances<SpriteInstance>; SPRITE_LOD_LEVELS],
)> {
match body { match body {
Body::Ship(body) => { Body::Ship(body) => {
if let Some(Collider::Volume(vol)) = collider { if let Some(Collider::Volume(vol)) = collider {
@ -6982,8 +6983,10 @@ impl FigureMgr {
mut_count: vol.mut_count, mut_count: vol.mut_count,
}; };
self.volume_model_cache.get_sprites(vk) self.volume_model_cache.get_sprites(vk)
} else { } else if body.manifest_entry().is_some() {
self.ship_model_cache.get_sprites(*body) self.ship_model_cache.get_sprites(*body)
} else {
None
} }
}, },
_ => None, _ => None,
@ -7195,8 +7198,6 @@ impl FigureColLights {
(tex, tex_size): ColLightInfo, (tex, tex_size): ColLightInfo,
(opaque, bounds): (Mesh<TerrainVertex>, math::Aabb<f32>), (opaque, bounds): (Mesh<TerrainVertex>, math::Aabb<f32>),
vertex_ranges: [Range<u32>; N], vertex_ranges: [Range<u32>; N],
pos: Vec3<f32>,
ori: Quaternion<f32>,
sprite_instances: [Vec<SpriteInstance>; SPRITE_LOD_LEVELS], sprite_instances: [Vec<SpriteInstance>; SPRITE_LOD_LEVELS],
blocks_of_interest: BlocksOfInterest, blocks_of_interest: BlocksOfInterest,
blocks_offset: Vec3<f32>, blocks_offset: Vec3<f32>,
@ -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 = let sprite_instances =
sprite_instances.map(|instances| renderer.create_instances(&instances)); sprite_instances.map(|instances| renderer.create_instances(&instances));
@ -7238,7 +7232,6 @@ impl FigureColLights {
col_lights, col_lights,
lod_vertex_ranges: vertex_ranges, lod_vertex_ranges: vertex_ranges,
model: FigureModel { opaque: model }, model: FigureModel { opaque: model },
terrain_locals,
sprite_instances, sprite_instances,
blocks_of_interest, blocks_of_interest,
blocks_offset, blocks_offset,
@ -7320,18 +7313,19 @@ impl FigureStateMeta {
} }
} }
pub struct FigureState<S> { pub struct FigureState<S, D = ()> {
meta: FigureStateMeta, meta: FigureStateMeta,
skeleton: S, skeleton: S,
extra: D,
} }
impl<S> Deref for FigureState<S> { impl<S, D> Deref for FigureState<S, D> {
type Target = FigureStateMeta; type Target = FigureStateMeta;
fn deref(&self) -> &Self::Target { &self.meta } fn deref(&self) -> &Self::Target { &self.meta }
} }
impl<S> DerefMut for FigureState<S> { impl<S, D> DerefMut for FigureState<S, D> {
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.meta } fn deref_mut(&mut self) -> &mut Self::Target { &mut self.meta }
} }
@ -7358,7 +7352,35 @@ pub struct FigureUpdateCommonParameters<'a> {
pub ground_vel: Vec3<f32>, pub ground_vel: Vec3<f32>,
} }
impl<S: Skeleton> FigureState<S> { 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<S: Skeleton, D: FigureData> FigureState<S, D> {
pub fn new(renderer: &mut Renderer, skeleton: S, body: S::Body) -> Self { pub fn new(renderer: &mut Renderer, skeleton: S, body: S::Body) -> Self {
let mut buf = [Default::default(); anim::MAX_BONE_COUNT]; let mut buf = [Default::default(); anim::MAX_BONE_COUNT];
let offsets = let offsets =
@ -7386,6 +7408,7 @@ impl<S: Skeleton> FigureState<S> {
bound: renderer.create_figure_bound_locals(&[FigureLocals::default()], bone_consts), bound: renderer.create_figure_bound_locals(&[FigureLocals::default()], bone_consts),
}, },
skeleton, skeleton,
extra: D::new(renderer),
} }
} }
@ -7394,7 +7417,7 @@ impl<S: Skeleton> FigureState<S> {
renderer: &mut Renderer, renderer: &mut Renderer,
trail_mgr: Option<&mut TrailMgr>, trail_mgr: Option<&mut TrailMgr>,
buf: &mut [anim::FigureBoneData; anim::MAX_BONE_COUNT], buf: &mut [anim::FigureBoneData; anim::MAX_BONE_COUNT],
FigureUpdateCommonParameters { parameters @ FigureUpdateCommonParameters {
entity, entity,
pos, pos,
ori, ori,
@ -7614,6 +7637,7 @@ impl<S: Skeleton> FigureState<S> {
} else { } else {
self.acc_vel = 0.0; self.acc_vel = 0.0;
} }
self.extra.update(renderer, parameters);
} }
pub fn bound(&self) -> &pipelines::figure::BoundLocals { &self.bound } pub fn bound(&self) -> &pipelines::figure::BoundLocals { &self.bound }