particles on volume

This commit is contained in:
Isse 2023-02-22 13:38:55 +01:00
parent 1710dcc111
commit 7fbe2cd5ec
5 changed files with 95 additions and 13 deletions

View File

@ -18,7 +18,7 @@
),
custom_indices: {
1: Air(Door, 4),
1: Air(ChairSingle, 4),
},
),
AirBalloon: (

View File

@ -31,7 +31,7 @@ use common::{
},
figure::{Segment, TerrainSegment},
slowjob::SlowJobPool,
vol::{BaseVol, IntoVolIterator},
vol::{BaseVol, IntoVolIterator, ReadVol},
};
use core::{hash::Hash, ops::Range};
use crossbeam_utils::atomic;
@ -58,6 +58,7 @@ pub struct TerrainMeshWorkerResponse<const N: usize> {
vertex_range: [Range<u32>; N],
sprite_instances: [Vec<SpriteInstance>; SPRITE_LOD_LEVELS],
blocks_of_interest: BlocksOfInterest,
blocks_offset: Vec3<f32>,
}
/// NOTE: To test this cell for validity, we currently first use
@ -655,6 +656,7 @@ where
vertex_range,
sprite_instances,
blocks_of_interest,
blocks_offset,
}) = Arc::get_mut(recv).take().and_then(|cell| cell.take())
{
let model_entry = col_lights.create_terrain(
@ -666,6 +668,7 @@ where
ori,
sprite_instances,
blocks_of_interest,
blocks_offset,
);
*model = TerrainModelEntryFuture::Done(model_entry);
// NOTE: Borrow checker isn't smart enough to figure this out.
@ -834,13 +837,16 @@ where
lod.push(instance);
},
block_iter.clone().map(|(pos, block)| (pos.as_() + *offset, block)),
|p| p.as_(), |_| 1.0, |_| 0.0,
|p| p.as_(),
|_| 1.0,
|pos| dyna.get(pos).ok().and_then(|block| block.get_glow()).map(|glow| glow as f32 / 255.0).unwrap_or(0.0),
&sprite_data,
&sprite_config,
);
instances
},
blocks_of_interest: BlocksOfInterest::from_blocks(block_iter, 0.0, 10.0, 0.0),
blocks_offset: *offset,
}));
});
@ -856,7 +862,10 @@ where
}
}
pub fn get_blocks_of_interest(&self, body: Skel::Body) -> Option<&BlocksOfInterest> {
pub fn get_blocks_of_interest(
&self,
body: Skel::Body,
) -> Option<(&BlocksOfInterest, Vec3<f32>)> {
let key = FigureKey {
body,
item_key: None,
@ -867,7 +876,7 @@ where
return None;
};
Some(&model.blocks_of_interest)
Some((&model.blocks_of_interest, model.blocks_offset))
})
}

View File

@ -143,6 +143,8 @@ pub struct TerrainModelEntry<const N: usize> {
lod_vertex_ranges: [Range<u32>; N],
model: FigureModel,
blocks_offset: Vec3<f32>,
terrain_locals: BoundTerrainLocals,
sprite_instances: [Instances<SpriteInstance>; SPRITE_LOD_LEVELS],
@ -6939,14 +6941,14 @@ impl FigureMgr {
}
}
fn get_sprite_instances(
&self,
fn get_sprite_instances<'a>(
&'a self,
entity: EcsEntity,
body: &Body,
collider: Option<&Collider>,
) -> Option<(
&BoundTerrainLocals,
&[Instances<SpriteInstance>; SPRITE_LOD_LEVELS],
&'a BoundTerrainLocals,
&'a [Instances<SpriteInstance>; SPRITE_LOD_LEVELS],
)> {
match body {
Body::Ship(body) => {
@ -6964,6 +6966,28 @@ impl FigureMgr {
}
}
pub fn get_blocks_of_interest<'a>(
&'a self,
entity: EcsEntity,
body: &Body,
collider: Option<&Collider>,
) -> Option<(&'a BlocksOfInterest, Vec3<f32>)> {
match body {
Body::Ship(body) => {
if let Some(Collider::Volume(vol)) = collider {
let vk = VolumeKey {
entity,
mut_count: vol.mut_count,
};
self.volume_model_cache.get_blocks_of_interest(vk)
} else {
self.ship_model_cache.get_blocks_of_interest(*body)
}
},
_ => None,
}
}
pub fn viewpoint_offset(&self, scene_data: &SceneData, entity: EcsEntity) -> Vec3<f32> {
scene_data
.state
@ -7151,6 +7175,7 @@ impl FigureColLights {
ori: Quaternion<f32>,
sprite_instances: [Vec<SpriteInstance>; SPRITE_LOD_LEVELS],
blocks_of_interest: BlocksOfInterest,
blocks_offset: Vec3<f32>,
) -> TerrainModelEntry<N> {
span!(_guard, "create_figure", "FigureColLights::create_figure");
let atlas = &mut self.atlas;
@ -7192,6 +7217,7 @@ impl FigureColLights {
terrain_locals,
sprite_instances,
blocks_of_interest,
blocks_offset,
}
}

View File

@ -655,8 +655,13 @@ impl Scene {
lights.clear();
// Maintain the particles.
self.particle_mgr
.maintain(renderer, scene_data, &self.terrain, lights);
self.particle_mgr.maintain(
renderer,
scene_data,
&self.terrain,
&self.figure_mgr,
lights,
);
// Maintain the trails.
self.trail_mgr.maintain(renderer, scene_data);

View File

@ -1,4 +1,4 @@
use super::{terrain::BlocksOfInterest, SceneData, Terrain};
use super::{terrain::BlocksOfInterest, FigureMgr, SceneData, Terrain};
use crate::{
ecs::comp::Interpolated,
mesh::{greedy::GreedyMesh, segment::generate_mesh_base_vol_particle},
@ -400,6 +400,7 @@ impl ParticleMgr {
renderer: &mut Renderer,
scene_data: &SceneData,
terrain: &Terrain<TerrainChunk>,
figure_mgr: &FigureMgr,
lights: &mut Vec<Light>,
) {
span!(_guard, "maintain", "ParticleMgr::maintain");
@ -415,7 +416,7 @@ impl ParticleMgr {
self.maintain_body_particles(scene_data);
self.maintain_char_state_particles(scene_data);
self.maintain_beam_particles(scene_data, lights);
self.maintain_block_particles(scene_data, terrain);
self.maintain_block_particles(scene_data, terrain, figure_mgr);
self.maintain_shockwave_particles(scene_data);
self.maintain_aura_particles(scene_data);
self.maintain_buff_particles(scene_data);
@ -1434,6 +1435,7 @@ impl ParticleMgr {
&mut self,
scene_data: &SceneData,
terrain: &Terrain<TerrainChunk>,
figure_mgr: &FigureMgr,
) {
span!(
_guard,
@ -1533,6 +1535,7 @@ impl ParticleMgr {
},
];
let ecs = scene_data.state.ecs();
let mut rng = thread_rng();
for particles in particles.iter() {
if !(particles.cond)(scene_data) {
@ -1564,6 +1567,45 @@ impl ParticleMgr {
})
});
}
for (entity, body, pos, ori, collider) in (
&ecs.entities(),
&ecs.read_storage::<comp::Body>(),
&ecs.read_storage::<comp::Pos>(),
&ecs.read_storage::<comp::Ori>(),
ecs.read_storage::<comp::Collider>().maybe(),
)
.join()
{
if let Some((blocks_of_interest, offset)) =
figure_mgr.get_blocks_of_interest(entity, body, collider)
{
let blocks = (particles.blocks)(blocks_of_interest);
let avg_particles = dt * blocks.len() as f32 * particles.rate;
let particle_count = avg_particles.trunc() as usize
+ (rng.gen::<f32>() < avg_particles.fract()) as usize;
self.particles
.resize_with(self.particles.len() + particle_count, || {
let rel_pos = blocks
.choose(&mut rng)
.copied()
.unwrap()
.map(|e: i32| e as f32 + rng.gen::<f32>()); // Can't fail
let wpos = (Mat4::from(ori.to_quat()).translated_3d(pos.0)
* (rel_pos + offset).with_w(1.0))
.xyz();
Particle::new(
Duration::from_secs_f32(particles.lifetime),
time,
particles.mode,
wpos,
)
})
}
}
}
// smoke is more complex as it comes with varying rate and color
{