mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Add particle velocity and ability particle emitter
This commit is contained in:
parent
da5f4828a5
commit
803677f0fb
@ -12,7 +12,7 @@ in vec4 inst_mat2;
|
||||
in vec4 inst_mat3;
|
||||
in vec3 inst_col;
|
||||
in vec3 inst_vel;
|
||||
in vec4 inst_tick;
|
||||
in vec4 inst_time;
|
||||
in float inst_wind_sway;
|
||||
|
||||
out vec3 f_pos;
|
||||
@ -30,20 +30,10 @@ void main() {
|
||||
inst_mat[2] = inst_mat2;
|
||||
inst_mat[3] = inst_mat3;
|
||||
|
||||
vec3 particle_pos = (inst_mat * vec4(0, 0, 0, 1)).xyz;
|
||||
|
||||
f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz;
|
||||
f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
|
||||
//f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
|
||||
|
||||
// Wind waving
|
||||
//f_pos += inst_wind_sway * vec3(
|
||||
// sin(tick.x * 1.5 + f_pos.y * 0.1) * sin(tick.x * 0.35),
|
||||
// sin(tick.x * 1.5 + f_pos.x * 0.1) * sin(tick.x * 0.25),
|
||||
// 0.0
|
||||
//) * pow(abs(v_pos.z) * SCALE, 1.3) * 0.2;
|
||||
|
||||
float elapsed = (tick.x - inst_tick.x) / 100000.0;
|
||||
f_pos += (inst_vel * elapsed);
|
||||
f_pos += inst_vel * (tick.x - inst_time.x);
|
||||
|
||||
// First 3 normals are negative, next 3 are positive
|
||||
vec3 normals[6] = vec3[](vec3(-1,0,0), vec3(1,0,0), vec3(0,-1,0), vec3(0,1,0), vec3(0,0,-1), vec3(0,0,1));
|
||||
@ -53,11 +43,6 @@ void main() {
|
||||
f_col = srgb_to_linear(col) * srgb_to_linear(inst_col);
|
||||
f_ao = float((v_norm_ao >> 3) & 0x3u) / 4.0;
|
||||
|
||||
// Select glowing
|
||||
if (select_pos.w > 0 && select_pos.xyz == floor(particle_pos)) {
|
||||
f_col *= 4.0;
|
||||
}
|
||||
|
||||
f_light = 1.0;
|
||||
|
||||
gl_Position =
|
||||
|
BIN
assets/voxygen/voxel/particle.vox
(Stored with Git LFS)
Normal file
BIN
assets/voxygen/voxel/particle.vox
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -62,7 +62,7 @@ pub enum CharacterAbility {
|
||||
projectile: Projectile,
|
||||
projectile_body: Body,
|
||||
projectile_light: Option<LightEmitter>,
|
||||
projectile_particles: Option<ParticleEmitter>,
|
||||
projectile_particles: Vec<ParticleEmitter>,
|
||||
projectile_gravity: Option<Gravity>,
|
||||
},
|
||||
Boost {
|
||||
@ -261,7 +261,7 @@ impl From<&CharacterAbility> for CharacterState {
|
||||
projectile: projectile.clone(),
|
||||
projectile_body: *projectile_body,
|
||||
projectile_light: *projectile_light,
|
||||
projectile_particles: *projectile_particles,
|
||||
projectile_particles: projectile_particles.clone().to_vec(),
|
||||
projectile_gravity: *projectile_gravity,
|
||||
}),
|
||||
CharacterAbility::Boost { duration, only_up } => CharacterState::Boost(boost::Data {
|
||||
|
@ -180,7 +180,7 @@ impl Tool {
|
||||
},
|
||||
projectile_body: Body::Object(object::Body::Arrow),
|
||||
projectile_light: None,
|
||||
projectile_particles: None,
|
||||
projectile_particles: vec![],
|
||||
projectile_gravity: Some(Gravity(0.2)),
|
||||
},
|
||||
ChargedRanged {
|
||||
@ -195,7 +195,7 @@ impl Tool {
|
||||
recover_duration: Duration::from_millis(500),
|
||||
projectile_body: Body::Object(object::Body::Arrow),
|
||||
projectile_light: None,
|
||||
projectile_particles: None,
|
||||
projectile_particles: vec![],
|
||||
projectile_gravity: Some(Gravity(0.05)),
|
||||
},
|
||||
],
|
||||
@ -276,7 +276,7 @@ impl Tool {
|
||||
col: (0.85, 0.5, 0.11).into(),
|
||||
..Default::default()
|
||||
}),
|
||||
projectile_particles: Some(ParticleEmitter {
|
||||
projectile_particles: vec![ParticleEmitter {
|
||||
mode: ParticleEmitterMode::Sprinkler,
|
||||
// model_key: "voxygen.voxel.not_found",
|
||||
count: (2, 3),
|
||||
@ -288,7 +288,8 @@ impl Tool {
|
||||
vek::Vec3::broadcast(1.0),
|
||||
),
|
||||
initial_scale: (0.1, 0.3),
|
||||
}),
|
||||
initial_velocity: (vek::Vec3::zero(), vek::Vec3::one()),
|
||||
}],
|
||||
projectile_gravity: None,
|
||||
},
|
||||
BasicRanged {
|
||||
@ -313,7 +314,7 @@ impl Tool {
|
||||
col: (1.0, 0.75, 0.11).into(),
|
||||
..Default::default()
|
||||
}),
|
||||
projectile_particles: Some(ParticleEmitter::default()),
|
||||
projectile_particles: vec![ParticleEmitter::default()],
|
||||
projectile_gravity: None,
|
||||
},
|
||||
],
|
||||
@ -358,7 +359,7 @@ impl Tool {
|
||||
col: (0.0, 1.0, 0.33).into(),
|
||||
..Default::default()
|
||||
}),
|
||||
projectile_particles: None,
|
||||
projectile_particles: vec![],
|
||||
projectile_gravity: None,
|
||||
},
|
||||
],
|
||||
|
@ -53,4 +53,4 @@ pub use player::{Player, MAX_MOUNT_RANGE_SQR};
|
||||
pub use projectile::Projectile;
|
||||
pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet};
|
||||
pub use stats::{Exp, HealthChange, HealthSource, Level, Stats};
|
||||
pub use visual::{LightAnimation, LightEmitter, ParticleEmitter};
|
||||
pub use visual::{LightAnimation, LightEmitter, ParticleEmitter, ParticleEmitters};
|
||||
|
@ -52,6 +52,13 @@ pub enum ParticleEmitterMode {
|
||||
Sprinkler,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] // Copy
|
||||
pub struct ParticleEmitters(pub Vec<ParticleEmitter>);
|
||||
|
||||
impl Default for ParticleEmitters {
|
||||
fn default() -> Self { Self(vec![ParticleEmitter::default()]) }
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct ParticleEmitter {
|
||||
pub mode: ParticleEmitterMode,
|
||||
@ -67,6 +74,7 @@ pub struct ParticleEmitter {
|
||||
pub initial_offset: (Vec3<f32>, Vec3<f32>), // fn() -> Vec3<f32>,
|
||||
pub initial_scale: (f32, f32), // fn() -> Vec3<f32>,
|
||||
pub initial_orientation: (Vec3<f32>, Vec3<f32>), // fn() -> Vec3<f32>,
|
||||
pub initial_velocity: (Vec3<f32>, Vec3<f32>), // fn() -> Vec3<f32>,
|
||||
}
|
||||
|
||||
impl Default for ParticleEmitter {
|
||||
@ -75,11 +83,15 @@ impl Default for ParticleEmitter {
|
||||
mode: ParticleEmitterMode::Sprinkler,
|
||||
// model_key: "voxygen.voxel.not_found",
|
||||
count: (2, 5),
|
||||
frequency: Duration::from_millis(500),
|
||||
initial_lifespan: Duration::from_secs(2),
|
||||
initial_offset: (vek::Vec3::broadcast(-5.0), vek::Vec3::broadcast(5.0)),
|
||||
initial_orientation: (vek::Vec3::broadcast(-5.0), vek::Vec3::broadcast(5.0)),
|
||||
frequency: Duration::from_millis(100),
|
||||
initial_lifespan: Duration::from_secs(20),
|
||||
initial_offset: (vek::Vec3::broadcast(-0.1), vek::Vec3::broadcast(0.1)),
|
||||
initial_orientation: (vek::Vec3::broadcast(0.0), vek::Vec3::broadcast(1.0)),
|
||||
initial_scale: (0.1, 2.0),
|
||||
initial_velocity: (
|
||||
vek::Vec3::new(0.0, 0.0, 0.2),
|
||||
vek::Vec3::new(0.01, 0.01, 1.0),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ pub enum ServerEvent {
|
||||
dir: Dir,
|
||||
body: comp::Body,
|
||||
light: Option<comp::LightEmitter>,
|
||||
particles: Option<comp::ParticleEmitter>,
|
||||
particles: Vec<comp::ParticleEmitter>,
|
||||
projectile: comp::Projectile,
|
||||
gravity: Option<comp::Gravity>,
|
||||
},
|
||||
|
@ -15,7 +15,7 @@ sum_type! {
|
||||
Stats(comp::Stats),
|
||||
Energy(comp::Energy),
|
||||
LightEmitter(comp::LightEmitter),
|
||||
ParticleEmitter(comp::ParticleEmitter),
|
||||
ParticleEmitter(comp::ParticleEmitters),
|
||||
Item(comp::Item),
|
||||
Scale(comp::Scale),
|
||||
Group(comp::Group),
|
||||
@ -43,7 +43,7 @@ sum_type! {
|
||||
Stats(PhantomData<comp::Stats>),
|
||||
Energy(PhantomData<comp::Energy>),
|
||||
LightEmitter(PhantomData<comp::LightEmitter>),
|
||||
ParticleEmitter(PhantomData<comp::ParticleEmitter>),
|
||||
ParticleEmitter(PhantomData<comp::ParticleEmitters>),
|
||||
Item(PhantomData<comp::Item>),
|
||||
Scale(PhantomData<comp::Scale>),
|
||||
Group(PhantomData<comp::Group>),
|
||||
@ -126,7 +126,7 @@ impl sync::CompPacket for EcsCompPacket {
|
||||
sync::handle_remove::<comp::LightEmitter>(entity, world)
|
||||
},
|
||||
EcsCompPhantom::ParticleEmitter(_) => {
|
||||
sync::handle_remove::<comp::ParticleEmitter>(entity, world)
|
||||
sync::handle_remove::<comp::ParticleEmitters>(entity, world)
|
||||
},
|
||||
EcsCompPhantom::Item(_) => sync::handle_remove::<comp::Item>(entity, world),
|
||||
EcsCompPhantom::Scale(_) => sync::handle_remove::<comp::Scale>(entity, world),
|
||||
|
@ -113,7 +113,7 @@ impl State {
|
||||
ecs.register::<comp::Energy>();
|
||||
ecs.register::<comp::CanBuild>();
|
||||
ecs.register::<comp::LightEmitter>();
|
||||
ecs.register::<comp::ParticleEmitter>();
|
||||
ecs.register::<comp::ParticleEmitters>();
|
||||
ecs.register::<comp::Item>();
|
||||
ecs.register::<comp::Scale>();
|
||||
ecs.register::<comp::Mounting>();
|
||||
|
@ -20,7 +20,7 @@ pub struct Data {
|
||||
pub projectile: Projectile,
|
||||
pub projectile_body: Body,
|
||||
pub projectile_light: Option<LightEmitter>,
|
||||
pub projectile_particles: Option<ParticleEmitter>,
|
||||
pub projectile_particles: Vec<ParticleEmitter>,
|
||||
pub projectile_gravity: Option<Gravity>,
|
||||
/// Whether the attack fired already
|
||||
pub exhausted: bool,
|
||||
@ -49,7 +49,7 @@ impl CharacterBehavior for Data {
|
||||
projectile: self.projectile.clone(),
|
||||
projectile_body: self.projectile_body,
|
||||
projectile_light: self.projectile_light,
|
||||
projectile_particles: self.projectile_particles,
|
||||
projectile_particles: self.projectile_particles.clone(),
|
||||
projectile_gravity: self.projectile_gravity,
|
||||
exhausted: false,
|
||||
});
|
||||
@ -63,7 +63,7 @@ impl CharacterBehavior for Data {
|
||||
body: self.projectile_body,
|
||||
projectile,
|
||||
light: self.projectile_light,
|
||||
particles: self.projectile_particles,
|
||||
particles: self.projectile_particles.clone(),
|
||||
gravity: self.projectile_gravity,
|
||||
});
|
||||
|
||||
@ -75,7 +75,7 @@ impl CharacterBehavior for Data {
|
||||
projectile: self.projectile.clone(),
|
||||
projectile_body: self.projectile_body,
|
||||
projectile_light: self.projectile_light,
|
||||
projectile_particles: self.projectile_particles,
|
||||
projectile_particles: self.projectile_particles.clone(),
|
||||
projectile_gravity: self.projectile_gravity,
|
||||
exhausted: true,
|
||||
});
|
||||
@ -92,7 +92,7 @@ impl CharacterBehavior for Data {
|
||||
projectile: self.projectile.clone(),
|
||||
projectile_body: self.projectile_body,
|
||||
projectile_light: self.projectile_light,
|
||||
projectile_particles: self.projectile_particles,
|
||||
projectile_particles: self.projectile_particles.clone(),
|
||||
projectile_gravity: self.projectile_gravity,
|
||||
exhausted: true,
|
||||
});
|
||||
|
@ -23,7 +23,6 @@ use specs::{Builder, Entity as EcsEntity, Join, WorldExt};
|
||||
use vek::*;
|
||||
use world::util::Sampler;
|
||||
|
||||
use comp::visual::ParticleEmitterMode;
|
||||
use scan_fmt::{scan_fmt, scan_fmt_some};
|
||||
use tracing::error;
|
||||
|
||||
@ -911,7 +910,7 @@ fn handle_light(
|
||||
.create_entity_synced()
|
||||
.with(pos)
|
||||
.with(comp::ForceUpdate)
|
||||
.with(comp::ParticleEmitter::default())
|
||||
.with(comp::ParticleEmitters::default())
|
||||
.with(light_emitter);
|
||||
if let Some(light_offset) = light_offset_opt {
|
||||
builder.with(light_offset).build();
|
||||
|
@ -2,11 +2,10 @@ use crate::{sys, Server, StateExt};
|
||||
use common::{
|
||||
comp::{
|
||||
self, Agent, Alignment, Body, Gravity, Item, ItemDrop, LightEmitter, Loadout,
|
||||
ParticleEmitter, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
||||
ParticleEmitter, ParticleEmitters, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
||||
},
|
||||
util::Dir,
|
||||
};
|
||||
use comp::visual::ParticleEmitterMode;
|
||||
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
||||
use vek::{Rgb, Vec3};
|
||||
|
||||
@ -78,7 +77,7 @@ pub fn handle_shoot(
|
||||
dir: Dir,
|
||||
body: Body,
|
||||
light: Option<LightEmitter>,
|
||||
particles: Option<ParticleEmitter>,
|
||||
particles: Vec<ParticleEmitter>,
|
||||
projectile: Projectile,
|
||||
gravity: Option<Gravity>,
|
||||
) {
|
||||
@ -98,9 +97,7 @@ pub fn handle_shoot(
|
||||
if let Some(light) = light {
|
||||
builder = builder.with(light)
|
||||
}
|
||||
if let Some(particles) = particles {
|
||||
builder = builder.with(particles)
|
||||
}
|
||||
builder = builder.with(ParticleEmitters(particles));
|
||||
if let Some(gravity) = gravity {
|
||||
builder = builder.with(gravity)
|
||||
}
|
||||
@ -118,7 +115,7 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
||||
flicker: 1.0,
|
||||
animated: true,
|
||||
})
|
||||
.with(ParticleEmitter::default())
|
||||
.with(ParticleEmitters::default())
|
||||
.with(WaypointArea::default())
|
||||
.build();
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ use super::SysTimer;
|
||||
use common::{
|
||||
comp::{
|
||||
Alignment, Body, CanBuild, CharacterState, Collider, Energy, Gravity, Item, LightEmitter,
|
||||
Loadout, Mass, MountState, Mounting, Ori, ParticleEmitter, Player, Pos, Scale, Stats,
|
||||
Sticky, Vel,
|
||||
Loadout, Mass, MountState, Mounting, Ori, ParticleEmitter, ParticleEmitters, Player, Pos,
|
||||
Scale, Stats, Sticky, Vel,
|
||||
},
|
||||
msg::EcsCompPacket,
|
||||
sync::{CompSyncPackage, EntityPackage, EntitySyncPackage, Uid, UpdateTracker, WorldSyncExt},
|
||||
@ -45,7 +45,7 @@ pub struct TrackedComps<'a> {
|
||||
pub energy: ReadStorage<'a, Energy>,
|
||||
pub can_build: ReadStorage<'a, CanBuild>,
|
||||
pub light_emitter: ReadStorage<'a, LightEmitter>,
|
||||
pub particle_emitter: ReadStorage<'a, ParticleEmitter>,
|
||||
pub particle_emitter: ReadStorage<'a, ParticleEmitters>,
|
||||
pub item: ReadStorage<'a, Item>,
|
||||
pub scale: ReadStorage<'a, Scale>,
|
||||
pub mounting: ReadStorage<'a, Mounting>,
|
||||
@ -96,7 +96,7 @@ impl<'a> TrackedComps<'a> {
|
||||
.map(|c| comps.push(c.into()));
|
||||
self.particle_emitter
|
||||
.get(entity)
|
||||
.copied()
|
||||
.cloned()
|
||||
.map(|c| comps.push(c.into()));
|
||||
self.item.get(entity).cloned().map(|c| comps.push(c.into()));
|
||||
self.scale
|
||||
@ -153,7 +153,7 @@ pub struct ReadTrackers<'a> {
|
||||
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
|
||||
pub can_build: ReadExpect<'a, UpdateTracker<CanBuild>>,
|
||||
pub light_emitter: ReadExpect<'a, UpdateTracker<LightEmitter>>,
|
||||
pub particle_emitter: ReadExpect<'a, UpdateTracker<ParticleEmitter>>,
|
||||
pub particle_emitter: ReadExpect<'a, UpdateTracker<ParticleEmitters>>,
|
||||
pub item: ReadExpect<'a, UpdateTracker<Item>>,
|
||||
pub scale: ReadExpect<'a, UpdateTracker<Scale>>,
|
||||
pub mounting: ReadExpect<'a, UpdateTracker<Mounting>>,
|
||||
@ -223,7 +223,7 @@ pub struct WriteTrackers<'a> {
|
||||
energy: WriteExpect<'a, UpdateTracker<Energy>>,
|
||||
can_build: WriteExpect<'a, UpdateTracker<CanBuild>>,
|
||||
light_emitter: WriteExpect<'a, UpdateTracker<LightEmitter>>,
|
||||
particle_emitter: WriteExpect<'a, UpdateTracker<ParticleEmitter>>,
|
||||
particle_emitter: WriteExpect<'a, UpdateTracker<ParticleEmitters>>,
|
||||
item: WriteExpect<'a, UpdateTracker<Item>>,
|
||||
scale: WriteExpect<'a, UpdateTracker<Scale>>,
|
||||
mounting: WriteExpect<'a, UpdateTracker<Mounting>>,
|
||||
@ -304,7 +304,7 @@ pub fn register_trackers(world: &mut World) {
|
||||
world.register_tracker::<Energy>();
|
||||
world.register_tracker::<CanBuild>();
|
||||
world.register_tracker::<LightEmitter>();
|
||||
world.register_tracker::<ParticleEmitter>();
|
||||
world.register_tracker::<ParticleEmitters>();
|
||||
world.register_tracker::<Item>();
|
||||
world.register_tracker::<Scale>();
|
||||
world.register_tracker::<Mounting>();
|
||||
|
@ -28,7 +28,7 @@ gfx_defines! {
|
||||
inst_mat3: [f32; 4] = "inst_mat3",
|
||||
inst_col: [f32; 3] = "inst_col",
|
||||
inst_vel: [f32; 3] = "inst_vel",
|
||||
inst_tick: [f32; 4] = "inst_tick",
|
||||
inst_time: [f32; 4] = "inst_time",
|
||||
inst_wind_sway: f32 = "inst_wind_sway",
|
||||
mode: u8 = "mode",
|
||||
}
|
||||
@ -74,7 +74,7 @@ impl Instance {
|
||||
mat: Mat4<f32>,
|
||||
col: Rgb<f32>,
|
||||
vel: Vec3<f32>,
|
||||
tick: u64,
|
||||
time: f64,
|
||||
wind_sway: f32,
|
||||
mode: ParticleEmitterMode,
|
||||
) -> Self {
|
||||
@ -86,7 +86,7 @@ impl Instance {
|
||||
inst_mat3: mat_arr[3],
|
||||
inst_col: col.into_array(),
|
||||
inst_vel: vel.into_array(),
|
||||
inst_tick: [tick as f32; 4],
|
||||
inst_time: [time as f32; 4],
|
||||
|
||||
inst_wind_sway: wind_sway,
|
||||
|
||||
@ -101,7 +101,7 @@ impl Default for Instance {
|
||||
Mat4::identity(),
|
||||
Rgb::broadcast(1.0),
|
||||
Vec3::zero(),
|
||||
0,
|
||||
0.0,
|
||||
0.0,
|
||||
ParticleEmitterMode::Sprinkler,
|
||||
)
|
||||
|
@ -2,22 +2,23 @@ use super::SceneData;
|
||||
use crate::{
|
||||
mesh::Meshable,
|
||||
render::{
|
||||
mesh::Quad, Consts, Globals, Instances, Light, Mesh, Model, ParticleInstance,
|
||||
ParticlePipeline, Renderer, Shadow,
|
||||
mesh::Quad, Consts, Globals, Instances, Light, Model, ParticleInstance, ParticlePipeline,
|
||||
Renderer, Shadow,
|
||||
},
|
||||
};
|
||||
use common::{
|
||||
assets,
|
||||
comp::{visual::ParticleEmitterMode, Ori, ParticleEmitter, Pos, Vel},
|
||||
comp::{
|
||||
visual::ParticleEmitterMode, CharacterState, Ori, ParticleEmitter, ParticleEmitters, Pos,
|
||||
Vel,
|
||||
},
|
||||
figure::Segment,
|
||||
vol::BaseVol,
|
||||
};
|
||||
use dot_vox::DotVoxData;
|
||||
use hashbrown::HashMap;
|
||||
use rand::Rng;
|
||||
use specs::{Entity as EcsEntity, Join, WorldExt};
|
||||
use std::time::{Duration, Instant};
|
||||
use tracing::{debug, error, warn};
|
||||
use vek::{Mat4, Rgb, Vec3};
|
||||
|
||||
struct Particles {
|
||||
@ -48,7 +49,7 @@ pub struct ParticleMgr {
|
||||
beginning_of_time: Instant,
|
||||
}
|
||||
|
||||
const MODEL_KEY: &str = "voxygen.voxel.not_found";
|
||||
const MODEL_KEY: &str = "voxygen.voxel.particle";
|
||||
|
||||
impl ParticleMgr {
|
||||
pub fn new(renderer: &mut Renderer) -> Self {
|
||||
@ -93,24 +94,34 @@ impl ParticleMgr {
|
||||
view_mat: Mat4<f32>,
|
||||
proj_mat: Mat4<f32>,
|
||||
) {
|
||||
let now = Instant::now();
|
||||
let state = scene_data.state;
|
||||
let ecs = state.ecs();
|
||||
|
||||
let tick = scene_data.tick;
|
||||
|
||||
let now = Instant::now();
|
||||
let beginning_of_time1 = self.beginning_of_time.clone();
|
||||
|
||||
// remove dead emitters
|
||||
self.emitters.retain(|k, _v| ecs.is_alive(*k));
|
||||
|
||||
// remove dead particles
|
||||
self.particles.retain(|p| p.alive_until > now);
|
||||
|
||||
// add living entities particles
|
||||
for (_i, (entity, particle_emitter, pos, ori, vel)) in (
|
||||
// add ParticleEmitter particles
|
||||
self.maintain_particle_emitter(renderer, scene_data);
|
||||
|
||||
self.maintain_ability_particles(renderer, scene_data);
|
||||
}
|
||||
|
||||
fn maintain_particle_emitter(&mut self, renderer: &mut Renderer, scene_data: &SceneData) {
|
||||
let state = scene_data.state;
|
||||
let ecs = state.ecs();
|
||||
|
||||
let time = state.get_time();
|
||||
|
||||
let now = Instant::now();
|
||||
let beginning_of_time1 = self.beginning_of_time.clone();
|
||||
|
||||
for (_i, (entity, particle_emitters, pos, ori, vel)) in (
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<ParticleEmitter>(),
|
||||
&ecs.read_storage::<ParticleEmitters>(),
|
||||
&ecs.read_storage::<Pos>(),
|
||||
ecs.read_storage::<Ori>().maybe(),
|
||||
ecs.read_storage::<Vel>().maybe(),
|
||||
@ -118,15 +129,78 @@ impl ParticleMgr {
|
||||
.join()
|
||||
.enumerate()
|
||||
{
|
||||
let emitter = self.emitters.entry(entity).or_insert_with(|| Emitter {
|
||||
last_emit: beginning_of_time1, // self.beginning_of_time.clone()
|
||||
});
|
||||
for particle_emitter in &particle_emitters.0 {
|
||||
// TODO: track multiple particle_emitter last_emit
|
||||
let emitter = self.emitters.entry(entity).or_insert_with(|| Emitter {
|
||||
last_emit: beginning_of_time1, // self.beginning_of_time.clone()
|
||||
});
|
||||
|
||||
if emitter.last_emit + particle_emitter.frequency < now {
|
||||
emitter.last_emit = Instant::now();
|
||||
if emitter.last_emit + particle_emitter.frequency < now {
|
||||
emitter.last_emit = Instant::now();
|
||||
|
||||
let cpu_insts =
|
||||
into_particle_instances(&particle_emitter, renderer, time, pos, ori, vel);
|
||||
|
||||
let gpu_insts = renderer
|
||||
.create_instances(&cpu_insts)
|
||||
.expect("Failed to upload particle instances to the GPU!");
|
||||
|
||||
let entry = self.particles.push(Particles {
|
||||
alive_until: now + particle_emitter.initial_lifespan,
|
||||
instances: gpu_insts,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn maintain_ability_particles(&mut self, renderer: &mut Renderer, scene_data: &SceneData) {
|
||||
let state = scene_data.state;
|
||||
let ecs = state.ecs();
|
||||
|
||||
let time = state.get_time();
|
||||
|
||||
let now = Instant::now();
|
||||
let beginning_of_time1 = self.beginning_of_time.clone();
|
||||
|
||||
for (_i, (entity, pos, character_state)) in (
|
||||
&ecs.entities(),
|
||||
//&ecs.read_storage::<ParticleEmitter>(),
|
||||
&ecs.read_storage::<Pos>(),
|
||||
&ecs.read_storage::<CharacterState>(),
|
||||
)
|
||||
.join()
|
||||
.enumerate()
|
||||
{
|
||||
// let emitter = self.emitters.entry(entity).or_insert_with(|| Emitter {
|
||||
// last_emit: beginning_of_time1, // self.beginning_of_time.clone()
|
||||
// });
|
||||
|
||||
// if emitter.last_emit + particle_emitter.frequency < now {
|
||||
// emitter.last_emit = Instant::now();
|
||||
// }
|
||||
|
||||
if let CharacterState::BasicMelee(melee_data) = character_state {
|
||||
// TODO: configure the emitter on the ability instead.
|
||||
let particle_emitter = ParticleEmitter {
|
||||
count: (30, 50),
|
||||
frequency: Duration::from_millis(1000), // doesn't matter
|
||||
initial_lifespan: Duration::from_millis(1000),
|
||||
initial_offset: (
|
||||
Vec3::new(1.0, -1.0, 0.0),
|
||||
Vec3::new(1.01, 1.0, 2.0), /* TODO: cone // melee_data.max_angle */
|
||||
),
|
||||
initial_orientation: (Vec3::zero(), Vec3::one()),
|
||||
initial_scale: (1.0, 3.0),
|
||||
mode: ParticleEmitterMode::Sprinkler,
|
||||
initial_velocity: (
|
||||
Vec3::new(1.0, 0.0, 0.0),
|
||||
Vec3::new(10.0, 0.01, 0.01), /* TODO: cone // melee_data.max_angle */
|
||||
),
|
||||
};
|
||||
|
||||
let cpu_insts =
|
||||
into_particle_instances(particle_emitter, renderer, tick, pos, ori, vel);
|
||||
into_particle_instances(&particle_emitter, renderer, time, pos, None, None);
|
||||
|
||||
let gpu_insts = renderer
|
||||
.create_instances(&cpu_insts)
|
||||
@ -166,7 +240,7 @@ impl ParticleMgr {
|
||||
fn into_particle_instances(
|
||||
particle_emitter: &ParticleEmitter,
|
||||
renderer: &mut Renderer,
|
||||
tick: u64,
|
||||
time: f64,
|
||||
pos: &Pos,
|
||||
ori: Option<&Ori>,
|
||||
vel: Option<&Vel>,
|
||||
@ -199,8 +273,13 @@ fn into_particle_instances(
|
||||
),
|
||||
),
|
||||
Rgb::broadcast(1.0), // instance color
|
||||
vel2 + Vec3::broadcast(rng.gen_range(-5.0, 5.0)),
|
||||
tick,
|
||||
vel2 // relative
|
||||
+ Vec3::new(
|
||||
rng.gen_range(particle_emitter.initial_velocity.0.x, particle_emitter.initial_velocity.1.x),
|
||||
rng.gen_range(particle_emitter.initial_velocity.0.y, particle_emitter.initial_velocity.1.y),
|
||||
rng.gen_range(particle_emitter.initial_velocity.0.z, particle_emitter.initial_velocity.1.z),
|
||||
),
|
||||
time,
|
||||
rng.gen_range(0.0, 20.0), // wind sway
|
||||
ParticleEmitterMode::Sprinkler, // particle_emitter.mode */
|
||||
));
|
||||
|
Loading…
Reference in New Issue
Block a user