mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
remove particle emitter component
This commit is contained in:
parent
3139e85dff
commit
4bc373a832
@ -10,10 +10,9 @@ in vec4 inst_mat0;
|
|||||||
in vec4 inst_mat1;
|
in vec4 inst_mat1;
|
||||||
in vec4 inst_mat2;
|
in vec4 inst_mat2;
|
||||||
in vec4 inst_mat3;
|
in vec4 inst_mat3;
|
||||||
in vec3 inst_col;
|
in float inst_time;
|
||||||
in vec3 inst_vel;
|
in float inst_entropy;
|
||||||
in vec4 inst_time;
|
in int inst_mode;
|
||||||
in float inst_wind_sway;
|
|
||||||
|
|
||||||
out vec3 f_pos;
|
out vec3 f_pos;
|
||||||
flat out vec3 f_norm;
|
flat out vec3 f_norm;
|
||||||
@ -23,6 +22,17 @@ out float f_light;
|
|||||||
|
|
||||||
const float SCALE = 1.0 / 11.0;
|
const float SCALE = 1.0 / 11.0;
|
||||||
|
|
||||||
|
float PHI = 1.61803398874989484820459; // Φ = Golden Ratio
|
||||||
|
|
||||||
|
float gold_noise(in vec2 xy, in float seed){
|
||||||
|
return fract(tan(distance(xy * PHI, xy) * seed) * xy.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modes
|
||||||
|
const int SMOKE = 0;
|
||||||
|
const int FIRE = 1;
|
||||||
|
const int FLAMETHROWER = 2;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
mat4 inst_mat;
|
mat4 inst_mat;
|
||||||
inst_mat[0] = inst_mat0;
|
inst_mat[0] = inst_mat0;
|
||||||
@ -30,10 +40,39 @@ void main() {
|
|||||||
inst_mat[2] = inst_mat2;
|
inst_mat[2] = inst_mat2;
|
||||||
inst_mat[3] = inst_mat3;
|
inst_mat[3] = inst_mat3;
|
||||||
|
|
||||||
f_pos = (inst_mat * vec4(v_pos * SCALE, 1)).xyz;
|
float rand1 = gold_noise(vec2(0.0, 0.0), inst_entropy);
|
||||||
//f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
|
float rand2 = gold_noise(vec2(1.0, 1.0), inst_entropy);
|
||||||
|
float rand3 = gold_noise(vec2(2.0, 2.0), inst_entropy);
|
||||||
|
float rand4 = gold_noise(vec2(3.0, 3.0), inst_entropy);
|
||||||
|
float rand5 = gold_noise(vec2(4.0, 4.0), inst_entropy);
|
||||||
|
float rand6 = gold_noise(vec2(5.0, 5.0), inst_entropy);
|
||||||
|
|
||||||
f_pos += inst_vel * (tick.x - inst_time.x);
|
vec3 inst_vel = vec3(0.0, 0.0, 0.0);
|
||||||
|
vec3 inst_pos = vec3(0.0, 0.0, 0.0);
|
||||||
|
vec3 inst_col = vec3(1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
if (inst_mode == SMOKE) {
|
||||||
|
inst_col = vec3(1.0, 1.0, 1.0);
|
||||||
|
inst_vel = vec3(rand1 * 0.2 - 0.1, rand2 * 0.2 - 0.1, 1.0 + rand3);
|
||||||
|
inst_pos = vec3(rand4 * 5.0 - 2.5, rand5 * 5.0 - 2.5, 0.0);
|
||||||
|
} else if (inst_mode == FIRE) {
|
||||||
|
inst_col = vec3(1.0, 1.0 * inst_entropy, 0.0);
|
||||||
|
inst_vel = vec3(rand1 * 0.2 - 0.1, rand2 * 0.2 - 0.1, 4.0 + rand3);
|
||||||
|
inst_pos = vec3(rand4 * 5.0 - 2.5, rand5 * 5.0 - 2.5, 0.0);
|
||||||
|
} else if (inst_mode == FLAMETHROWER) {
|
||||||
|
// TODO: velocity based on attack range, angle and parent orientation.
|
||||||
|
inst_col = vec3(1.0, 1.0 * inst_entropy, 0.0);
|
||||||
|
inst_vel = vec3(rand1 * 0.1, rand2 * 0.1, 3.0 + rand3);
|
||||||
|
inst_pos = vec3(rand4 * 5.0 - 2.5, rand5 * 5.0 - 2.5, 0.0);
|
||||||
|
} else {
|
||||||
|
inst_col = vec3(rand1, rand2, rand3);
|
||||||
|
inst_vel = vec3(rand4, rand5, rand6);
|
||||||
|
inst_pos = vec3(rand1, rand2, rand3);
|
||||||
|
}
|
||||||
|
|
||||||
|
f_pos = (inst_mat * vec4((v_pos + inst_pos) * SCALE, 1)).xyz;
|
||||||
|
|
||||||
|
f_pos += inst_vel * (tick.x - inst_time);
|
||||||
|
|
||||||
// First 3 normals are negative, next 3 are positive
|
// 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));
|
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));
|
||||||
|
@ -2,8 +2,7 @@ use crate::{
|
|||||||
comp::{
|
comp::{
|
||||||
ability::Stage,
|
ability::Stage,
|
||||||
item::{armor::Protection, Item, ItemKind},
|
item::{armor::Protection, Item, ItemKind},
|
||||||
Body, CharacterState, EnergySource, Gravity, LightEmitter, ParticleEmitter, Projectile,
|
Body, CharacterState, EnergySource, Gravity, LightEmitter, Projectile, StateUpdate,
|
||||||
StateUpdate,
|
|
||||||
},
|
},
|
||||||
states::{triple_strike::*, *},
|
states::{triple_strike::*, *},
|
||||||
sys::character_behavior::JoinData,
|
sys::character_behavior::JoinData,
|
||||||
@ -62,7 +61,6 @@ pub enum CharacterAbility {
|
|||||||
projectile: Projectile,
|
projectile: Projectile,
|
||||||
projectile_body: Body,
|
projectile_body: Body,
|
||||||
projectile_light: Option<LightEmitter>,
|
projectile_light: Option<LightEmitter>,
|
||||||
projectile_particles: Vec<ParticleEmitter>,
|
|
||||||
projectile_gravity: Option<Gravity>,
|
projectile_gravity: Option<Gravity>,
|
||||||
},
|
},
|
||||||
Boost {
|
Boost {
|
||||||
@ -249,7 +247,6 @@ impl From<&CharacterAbility> for CharacterState {
|
|||||||
projectile,
|
projectile,
|
||||||
projectile_body,
|
projectile_body,
|
||||||
projectile_light,
|
projectile_light,
|
||||||
projectile_particles,
|
|
||||||
projectile_gravity,
|
projectile_gravity,
|
||||||
energy_cost: _,
|
energy_cost: _,
|
||||||
} => CharacterState::BasicRanged(basic_ranged::Data {
|
} => CharacterState::BasicRanged(basic_ranged::Data {
|
||||||
@ -261,7 +258,6 @@ impl From<&CharacterAbility> for CharacterState {
|
|||||||
projectile: projectile.clone(),
|
projectile: projectile.clone(),
|
||||||
projectile_body: *projectile_body,
|
projectile_body: *projectile_body,
|
||||||
projectile_light: *projectile_light,
|
projectile_light: *projectile_light,
|
||||||
projectile_particles: projectile_particles.clone().to_vec(),
|
|
||||||
projectile_gravity: *projectile_gravity,
|
projectile_gravity: *projectile_gravity,
|
||||||
}),
|
}),
|
||||||
CharacterAbility::Boost { duration, only_up } => CharacterState::Boost(boost::Data {
|
CharacterAbility::Boost { duration, only_up } => CharacterState::Boost(boost::Data {
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
// version in voxygen\src\meta.rs in order to reset save files to being empty
|
// version in voxygen\src\meta.rs in order to reset save files to being empty
|
||||||
|
|
||||||
use crate::comp::{
|
use crate::comp::{
|
||||||
body::object, projectile, visual::ParticleEmitterMode, Body, CharacterAbility, Gravity,
|
body::object, projectile, Body, CharacterAbility, Gravity, HealthChange, HealthSource,
|
||||||
HealthChange, HealthSource, LightEmitter, ParticleEmitter, Projectile,
|
LightEmitter, Projectile,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -180,7 +180,6 @@ impl Tool {
|
|||||||
},
|
},
|
||||||
projectile_body: Body::Object(object::Body::Arrow),
|
projectile_body: Body::Object(object::Body::Arrow),
|
||||||
projectile_light: None,
|
projectile_light: None,
|
||||||
projectile_particles: vec![],
|
|
||||||
projectile_gravity: Some(Gravity(0.2)),
|
projectile_gravity: Some(Gravity(0.2)),
|
||||||
},
|
},
|
||||||
ChargedRanged {
|
ChargedRanged {
|
||||||
@ -195,7 +194,6 @@ impl Tool {
|
|||||||
recover_duration: Duration::from_millis(500),
|
recover_duration: Duration::from_millis(500),
|
||||||
projectile_body: Body::Object(object::Body::Arrow),
|
projectile_body: Body::Object(object::Body::Arrow),
|
||||||
projectile_light: None,
|
projectile_light: None,
|
||||||
projectile_particles: vec![],
|
|
||||||
projectile_gravity: Some(Gravity(0.05)),
|
projectile_gravity: Some(Gravity(0.05)),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -276,21 +274,6 @@ impl Tool {
|
|||||||
col: (0.85, 0.5, 0.11).into(),
|
col: (0.85, 0.5, 0.11).into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
projectile_particles: vec![ParticleEmitter {
|
|
||||||
mode: ParticleEmitterMode::Sprinkler,
|
|
||||||
// model_key: "voxygen.voxel.not_found",
|
|
||||||
count: (2, 3),
|
|
||||||
frequency: Duration::from_millis(50),
|
|
||||||
initial_lifespan: Duration::from_millis(500),
|
|
||||||
initial_offset: (vek::Vec3::broadcast(-1.0), vek::Vec3::broadcast(1.0)),
|
|
||||||
initial_orientation: (
|
|
||||||
vek::Vec3::broadcast(-1.0),
|
|
||||||
vek::Vec3::broadcast(1.0),
|
|
||||||
),
|
|
||||||
initial_scale: (0.1, 0.3),
|
|
||||||
initial_velocity: (vek::Vec3::zero(), vek::Vec3::one()),
|
|
||||||
initial_col: (vek::Rgb::zero(), vek::Rgb::one()),
|
|
||||||
}],
|
|
||||||
projectile_gravity: None,
|
projectile_gravity: None,
|
||||||
},
|
},
|
||||||
BasicRanged {
|
BasicRanged {
|
||||||
@ -315,7 +298,6 @@ impl Tool {
|
|||||||
col: (1.0, 0.75, 0.11).into(),
|
col: (1.0, 0.75, 0.11).into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
projectile_particles: vec![ParticleEmitter::default()],
|
|
||||||
projectile_gravity: None,
|
projectile_gravity: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -360,7 +342,6 @@ impl Tool {
|
|||||||
col: (0.0, 1.0, 0.33).into(),
|
col: (0.0, 1.0, 0.33).into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}),
|
}),
|
||||||
projectile_particles: vec![],
|
|
||||||
projectile_gravity: None,
|
projectile_gravity: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -53,4 +53,4 @@ pub use player::{Player, MAX_MOUNT_RANGE_SQR};
|
|||||||
pub use projectile::Projectile;
|
pub use projectile::Projectile;
|
||||||
pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet};
|
pub use skills::{Skill, SkillGroup, SkillGroupType, SkillSet};
|
||||||
pub use stats::{Exp, HealthChange, HealthSource, Level, Stats};
|
pub use stats::{Exp, HealthChange, HealthSource, Level, Stats};
|
||||||
pub use visual::{LightAnimation, LightEmitter, ParticleEmitter, ParticleEmitters};
|
pub use visual::{LightAnimation, LightEmitter};
|
||||||
|
@ -24,6 +24,10 @@ impl Component for Vel {
|
|||||||
#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Ori(pub Dir);
|
pub struct Ori(pub Dir);
|
||||||
|
|
||||||
|
impl Ori {
|
||||||
|
pub fn vec(&self) -> &Vec3<f32> { &self.0.vec() }
|
||||||
|
}
|
||||||
|
|
||||||
impl Component for Ori {
|
impl Component for Ori {
|
||||||
type Storage = IdvStorage<Self>;
|
type Storage = IdvStorage<Self>;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, FlaggedStorage};
|
use specs::{Component, FlaggedStorage};
|
||||||
use specs_idvs::IdvStorage;
|
use specs_idvs::IdvStorage;
|
||||||
use std::time::Duration;
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -47,67 +46,67 @@ impl Default for LightAnimation {
|
|||||||
impl Component for LightAnimation {
|
impl Component for LightAnimation {
|
||||||
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
||||||
}
|
}
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
// #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum ParticleEmitterMode {
|
// pub enum ParticleEmitterMode {
|
||||||
Sprinkler,
|
// Sprinkler,
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] // Copy
|
// #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] // Copy
|
||||||
pub struct ParticleEmitters(pub Vec<ParticleEmitter>);
|
// pub struct ParticleEmitters(pub Vec<ParticleEmitter>);
|
||||||
|
|
||||||
impl Default for ParticleEmitters {
|
// impl Default for ParticleEmitters {
|
||||||
fn default() -> Self {
|
// fn default() -> Self {
|
||||||
Self(vec![ParticleEmitter::default(), ParticleEmitter {
|
// Self(vec![ParticleEmitter::default(), ParticleEmitter {
|
||||||
mode: ParticleEmitterMode::Sprinkler,
|
// mode: ParticleEmitterMode::Sprinkler,
|
||||||
// model_key: "voxygen.voxel.not_found",
|
// // model_key: "voxygen.voxel.not_found",
|
||||||
count: (7, 10),
|
// count: (7, 10),
|
||||||
frequency: Duration::from_millis(100),
|
// frequency: Duration::from_millis(100),
|
||||||
initial_lifespan: Duration::from_secs(500),
|
// initial_lifespan: Duration::from_millis(500),
|
||||||
initial_offset: (Vec3::broadcast(-0.2), Vec3::broadcast(0.2)),
|
// initial_offset: (Vec3::broadcast(-0.2), Vec3::broadcast(0.2)),
|
||||||
initial_orientation: (Vec3::broadcast(0.0), Vec3::broadcast(1.0)),
|
// initial_orientation: (Vec3::broadcast(0.0),
|
||||||
initial_scale: (1.0, 2.0),
|
// Vec3::broadcast(1.0)), initial_scale: (1.0, 2.5),
|
||||||
initial_velocity: (Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.01, 0.01, 3.0)),
|
// initial_velocity: (Vec3::new(0.0, 0.0, 1.0), Vec3::new(0.01,
|
||||||
initial_col: (Rgb::new(0.999, 0.0, 0.0), Rgb::new(1.0, 1.0, 0.001)),
|
// 0.01, 3.0)), initial_col: (Rgb::new(0.999, 0.0, 0.0),
|
||||||
}])
|
// Rgb::new(1.0, 1.0, 0.001)), }])
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
// #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ParticleEmitter {
|
// pub struct ParticleEmitter {
|
||||||
pub mode: ParticleEmitterMode,
|
// pub mode: ParticleEmitterMode,
|
||||||
|
|
||||||
// spawn X particles per Y, that live for Z
|
// // spawn X particles per Y, that live for Z
|
||||||
// pub model_ref: &str, // can we have some kind of stack based key like a u8?
|
// // pub model_ref: &str, // can we have some kind of stack based key like
|
||||||
pub count: (u8, u8),
|
// a u8? pub count: (u8, u8),
|
||||||
pub frequency: Duration,
|
// pub frequency: Duration,
|
||||||
|
|
||||||
// relative to Pos, Ori components?
|
// // relative to Pos, Ori components?
|
||||||
// can these be functions that returns a Vec3<f32>?
|
// // can these be functions that returns a Vec3<f32>?
|
||||||
pub initial_lifespan: Duration,
|
// pub initial_lifespan: Duration,
|
||||||
pub initial_offset: (Vec3<f32>, Vec3<f32>), // fn() -> Vec3<f32>,
|
// pub initial_offset: (Vec3<f32>, Vec3<f32>), // fn() -> Vec3<f32>,
|
||||||
pub initial_scale: (f32, f32), // fn() -> Vec3<f32>,
|
// pub initial_scale: (f32, f32), // fn() -> Vec3<f32>,
|
||||||
pub initial_orientation: (Vec3<f32>, Vec3<f32>), // fn() -> Vec3<f32>,
|
// pub initial_orientation: (Vec3<f32>, Vec3<f32>), // fn() -> Vec3<f32>,
|
||||||
pub initial_velocity: (Vec3<f32>, Vec3<f32>), // fn() -> Vec3<f32>,
|
// pub initial_velocity: (Vec3<f32>, Vec3<f32>), // fn() -> Vec3<f32>,
|
||||||
pub initial_col: (Rgb<f32>, Rgb<f32>), // fn() -> Vec3<f32>,
|
// pub initial_col: (Rgb<f32>, Rgb<f32>), // fn() -> Vec3<f32>,
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Default for ParticleEmitter {
|
// impl Default for ParticleEmitter {
|
||||||
fn default() -> Self {
|
// fn default() -> Self {
|
||||||
Self {
|
// Self {
|
||||||
mode: ParticleEmitterMode::Sprinkler,
|
// mode: ParticleEmitterMode::Sprinkler,
|
||||||
// model_key: "voxygen.voxel.not_found",
|
// // model_key: "voxygen.voxel.not_found",
|
||||||
count: (2, 5),
|
// count: (2, 5),
|
||||||
frequency: Duration::from_millis(100),
|
// frequency: Duration::from_millis(100),
|
||||||
initial_lifespan: Duration::from_secs(20),
|
// initial_lifespan: Duration::from_secs(20),
|
||||||
initial_offset: (Vec3::broadcast(-0.1), Vec3::broadcast(0.1)),
|
// initial_offset: (Vec3::broadcast(-0.1), Vec3::broadcast(0.1)),
|
||||||
initial_orientation: (Vec3::broadcast(0.0), Vec3::broadcast(1.0)),
|
// initial_orientation: (Vec3::broadcast(0.0),
|
||||||
initial_scale: (0.1, 2.0),
|
// Vec3::broadcast(1.0)), initial_scale: (0.1, 2.0),
|
||||||
initial_velocity: (Vec3::new(0.0, 0.0, 0.2), Vec3::new(0.01, 0.01, 1.0)),
|
// initial_velocity: (Vec3::new(0.0, 0.0, 0.2), Vec3::new(0.01,
|
||||||
initial_col: (Rgb::new(0.999, 0.999, 0.999), Rgb::new(1.0, 1.0, 1.0)),
|
// 0.01, 1.0)), initial_col: (Rgb::new(0.999, 0.999, 0.999),
|
||||||
}
|
// Rgb::new(1.0, 1.0, 1.0)), }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl Component for ParticleEmitter {
|
// impl Component for ParticleEmitter {
|
||||||
type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
// type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
|
||||||
}
|
// }
|
||||||
|
@ -43,7 +43,6 @@ pub enum ServerEvent {
|
|||||||
dir: Dir,
|
dir: Dir,
|
||||||
body: comp::Body,
|
body: comp::Body,
|
||||||
light: Option<comp::LightEmitter>,
|
light: Option<comp::LightEmitter>,
|
||||||
particles: Vec<comp::ParticleEmitter>,
|
|
||||||
projectile: comp::Projectile,
|
projectile: comp::Projectile,
|
||||||
gravity: Option<comp::Gravity>,
|
gravity: Option<comp::Gravity>,
|
||||||
},
|
},
|
||||||
|
@ -15,7 +15,6 @@ sum_type! {
|
|||||||
Stats(comp::Stats),
|
Stats(comp::Stats),
|
||||||
Energy(comp::Energy),
|
Energy(comp::Energy),
|
||||||
LightEmitter(comp::LightEmitter),
|
LightEmitter(comp::LightEmitter),
|
||||||
ParticleEmitter(comp::ParticleEmitters),
|
|
||||||
Item(comp::Item),
|
Item(comp::Item),
|
||||||
Scale(comp::Scale),
|
Scale(comp::Scale),
|
||||||
Group(comp::Group),
|
Group(comp::Group),
|
||||||
@ -43,7 +42,6 @@ sum_type! {
|
|||||||
Stats(PhantomData<comp::Stats>),
|
Stats(PhantomData<comp::Stats>),
|
||||||
Energy(PhantomData<comp::Energy>),
|
Energy(PhantomData<comp::Energy>),
|
||||||
LightEmitter(PhantomData<comp::LightEmitter>),
|
LightEmitter(PhantomData<comp::LightEmitter>),
|
||||||
ParticleEmitter(PhantomData<comp::ParticleEmitters>),
|
|
||||||
Item(PhantomData<comp::Item>),
|
Item(PhantomData<comp::Item>),
|
||||||
Scale(PhantomData<comp::Scale>),
|
Scale(PhantomData<comp::Scale>),
|
||||||
Group(PhantomData<comp::Group>),
|
Group(PhantomData<comp::Group>),
|
||||||
@ -71,7 +69,6 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::ParticleEmitter(comp) => sync::handle_insert(comp, entity, world),
|
|
||||||
EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Scale(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Scale(comp) => sync::handle_insert(comp, entity, world),
|
||||||
EcsCompPacket::Group(comp) => sync::handle_insert(comp, entity, world),
|
EcsCompPacket::Group(comp) => sync::handle_insert(comp, entity, world),
|
||||||
@ -97,7 +94,6 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::ParticleEmitter(comp) => sync::handle_modify(comp, entity, world),
|
|
||||||
EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Scale(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Scale(comp) => sync::handle_modify(comp, entity, world),
|
||||||
EcsCompPacket::Group(comp) => sync::handle_modify(comp, entity, world),
|
EcsCompPacket::Group(comp) => sync::handle_modify(comp, entity, world),
|
||||||
@ -125,9 +121,6 @@ impl sync::CompPacket for EcsCompPacket {
|
|||||||
EcsCompPhantom::LightEmitter(_) => {
|
EcsCompPhantom::LightEmitter(_) => {
|
||||||
sync::handle_remove::<comp::LightEmitter>(entity, world)
|
sync::handle_remove::<comp::LightEmitter>(entity, world)
|
||||||
},
|
},
|
||||||
EcsCompPhantom::ParticleEmitter(_) => {
|
|
||||||
sync::handle_remove::<comp::ParticleEmitters>(entity, world)
|
|
||||||
},
|
|
||||||
EcsCompPhantom::Item(_) => sync::handle_remove::<comp::Item>(entity, world),
|
EcsCompPhantom::Item(_) => sync::handle_remove::<comp::Item>(entity, world),
|
||||||
EcsCompPhantom::Scale(_) => sync::handle_remove::<comp::Scale>(entity, world),
|
EcsCompPhantom::Scale(_) => sync::handle_remove::<comp::Scale>(entity, world),
|
||||||
EcsCompPhantom::Group(_) => sync::handle_remove::<comp::Group>(entity, world),
|
EcsCompPhantom::Group(_) => sync::handle_remove::<comp::Group>(entity, world),
|
||||||
|
@ -113,7 +113,6 @@ impl State {
|
|||||||
ecs.register::<comp::Energy>();
|
ecs.register::<comp::Energy>();
|
||||||
ecs.register::<comp::CanBuild>();
|
ecs.register::<comp::CanBuild>();
|
||||||
ecs.register::<comp::LightEmitter>();
|
ecs.register::<comp::LightEmitter>();
|
||||||
ecs.register::<comp::ParticleEmitters>();
|
|
||||||
ecs.register::<comp::Item>();
|
ecs.register::<comp::Item>();
|
||||||
ecs.register::<comp::Scale>();
|
ecs.register::<comp::Scale>();
|
||||||
ecs.register::<comp::Mounting>();
|
ecs.register::<comp::Mounting>();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{Body, CharacterState, Gravity, LightEmitter, ParticleEmitter, Projectile, StateUpdate},
|
comp::{Body, CharacterState, Gravity, LightEmitter, Projectile, StateUpdate},
|
||||||
event::ServerEvent,
|
event::ServerEvent,
|
||||||
states::utils::*,
|
states::utils::*,
|
||||||
sys::character_behavior::*,
|
sys::character_behavior::*,
|
||||||
@ -20,7 +20,6 @@ pub struct Data {
|
|||||||
pub projectile: Projectile,
|
pub projectile: Projectile,
|
||||||
pub projectile_body: Body,
|
pub projectile_body: Body,
|
||||||
pub projectile_light: Option<LightEmitter>,
|
pub projectile_light: Option<LightEmitter>,
|
||||||
pub projectile_particles: Vec<ParticleEmitter>,
|
|
||||||
pub projectile_gravity: Option<Gravity>,
|
pub projectile_gravity: Option<Gravity>,
|
||||||
/// Whether the attack fired already
|
/// Whether the attack fired already
|
||||||
pub exhausted: bool,
|
pub exhausted: bool,
|
||||||
@ -49,7 +48,6 @@ impl CharacterBehavior for Data {
|
|||||||
projectile: self.projectile.clone(),
|
projectile: self.projectile.clone(),
|
||||||
projectile_body: self.projectile_body,
|
projectile_body: self.projectile_body,
|
||||||
projectile_light: self.projectile_light,
|
projectile_light: self.projectile_light,
|
||||||
projectile_particles: self.projectile_particles.clone(),
|
|
||||||
projectile_gravity: self.projectile_gravity,
|
projectile_gravity: self.projectile_gravity,
|
||||||
exhausted: false,
|
exhausted: false,
|
||||||
});
|
});
|
||||||
@ -63,7 +61,6 @@ impl CharacterBehavior for Data {
|
|||||||
body: self.projectile_body,
|
body: self.projectile_body,
|
||||||
projectile,
|
projectile,
|
||||||
light: self.projectile_light,
|
light: self.projectile_light,
|
||||||
particles: self.projectile_particles.clone(),
|
|
||||||
gravity: self.projectile_gravity,
|
gravity: self.projectile_gravity,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -75,7 +72,6 @@ impl CharacterBehavior for Data {
|
|||||||
projectile: self.projectile.clone(),
|
projectile: self.projectile.clone(),
|
||||||
projectile_body: self.projectile_body,
|
projectile_body: self.projectile_body,
|
||||||
projectile_light: self.projectile_light,
|
projectile_light: self.projectile_light,
|
||||||
projectile_particles: self.projectile_particles.clone(),
|
|
||||||
projectile_gravity: self.projectile_gravity,
|
projectile_gravity: self.projectile_gravity,
|
||||||
exhausted: true,
|
exhausted: true,
|
||||||
});
|
});
|
||||||
@ -92,7 +88,6 @@ impl CharacterBehavior for Data {
|
|||||||
projectile: self.projectile.clone(),
|
projectile: self.projectile.clone(),
|
||||||
projectile_body: self.projectile_body,
|
projectile_body: self.projectile_body,
|
||||||
projectile_light: self.projectile_light,
|
projectile_light: self.projectile_light,
|
||||||
projectile_particles: self.projectile_particles.clone(),
|
|
||||||
projectile_gravity: self.projectile_gravity,
|
projectile_gravity: self.projectile_gravity,
|
||||||
exhausted: true,
|
exhausted: true,
|
||||||
});
|
});
|
||||||
|
@ -87,6 +87,8 @@ impl Dir {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_valid(&self) -> bool { !self.0.map(f32::is_nan).reduce_or() && self.is_normalized() }
|
pub fn is_valid(&self) -> bool { !self.0.map(f32::is_nan).reduce_or() && self.is_normalized() }
|
||||||
|
|
||||||
|
pub fn vec(&self) -> &Vec3<f32> { &self.0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::ops::Deref for Dir {
|
impl std::ops::Deref for Dir {
|
||||||
|
@ -910,7 +910,6 @@ fn handle_light(
|
|||||||
.create_entity_synced()
|
.create_entity_synced()
|
||||||
.with(pos)
|
.with(pos)
|
||||||
.with(comp::ForceUpdate)
|
.with(comp::ForceUpdate)
|
||||||
.with(comp::ParticleEmitters::default())
|
|
||||||
.with(light_emitter);
|
.with(light_emitter);
|
||||||
if let Some(light_offset) = light_offset_opt {
|
if let Some(light_offset) = light_offset_opt {
|
||||||
builder.with(light_offset).build();
|
builder.with(light_offset).build();
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::{sys, Server, StateExt};
|
use crate::{sys, Server, StateExt};
|
||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
self, Agent, Alignment, Body, Gravity, Item, ItemDrop, LightEmitter, Loadout,
|
self, Agent, Alignment, Body, Gravity, Item, ItemDrop, LightEmitter, Loadout, Pos,
|
||||||
ParticleEmitter, ParticleEmitters, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
Projectile, Scale, Stats, Vel, WaypointArea,
|
||||||
},
|
},
|
||||||
util::Dir,
|
util::Dir,
|
||||||
};
|
};
|
||||||
@ -77,7 +77,6 @@ pub fn handle_shoot(
|
|||||||
dir: Dir,
|
dir: Dir,
|
||||||
body: Body,
|
body: Body,
|
||||||
light: Option<LightEmitter>,
|
light: Option<LightEmitter>,
|
||||||
particles: Vec<ParticleEmitter>,
|
|
||||||
projectile: Projectile,
|
projectile: Projectile,
|
||||||
gravity: Option<Gravity>,
|
gravity: Option<Gravity>,
|
||||||
) {
|
) {
|
||||||
@ -97,7 +96,6 @@ pub fn handle_shoot(
|
|||||||
if let Some(light) = light {
|
if let Some(light) = light {
|
||||||
builder = builder.with(light)
|
builder = builder.with(light)
|
||||||
}
|
}
|
||||||
builder = builder.with(ParticleEmitters(particles));
|
|
||||||
if let Some(gravity) = gravity {
|
if let Some(gravity) = gravity {
|
||||||
builder = builder.with(gravity)
|
builder = builder.with(gravity)
|
||||||
}
|
}
|
||||||
@ -115,7 +113,6 @@ pub fn handle_create_waypoint(server: &mut Server, pos: Vec3<f32>) {
|
|||||||
flicker: 1.0,
|
flicker: 1.0,
|
||||||
animated: true,
|
animated: true,
|
||||||
})
|
})
|
||||||
.with(ParticleEmitters::default())
|
|
||||||
.with(WaypointArea::default())
|
.with(WaypointArea::default())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -61,10 +61,9 @@ impl Server {
|
|||||||
dir,
|
dir,
|
||||||
body,
|
body,
|
||||||
light,
|
light,
|
||||||
particles,
|
|
||||||
projectile,
|
projectile,
|
||||||
gravity,
|
gravity,
|
||||||
} => handle_shoot(self, entity, dir, body, light, particles, projectile, gravity),
|
} => handle_shoot(self, entity, dir, body, light, projectile, gravity),
|
||||||
ServerEvent::Damage { uid, change } => handle_damage(&self, uid, change),
|
ServerEvent::Damage { uid, change } => handle_damage(&self, uid, change),
|
||||||
ServerEvent::Destroy { entity, cause } => handle_destroy(self, entity, cause),
|
ServerEvent::Destroy { entity, cause } => handle_destroy(self, entity, cause),
|
||||||
ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip),
|
ServerEvent::InventoryManip(entity, manip) => handle_inventory(self, entity, manip),
|
||||||
|
@ -2,7 +2,7 @@ use super::SysTimer;
|
|||||||
use common::{
|
use common::{
|
||||||
comp::{
|
comp::{
|
||||||
Alignment, Body, CanBuild, CharacterState, Collider, Energy, Gravity, Item, LightEmitter,
|
Alignment, Body, CanBuild, CharacterState, Collider, Energy, Gravity, Item, LightEmitter,
|
||||||
Loadout, Mass, MountState, Mounting, Ori, ParticleEmitter, ParticleEmitters, Player, Pos,
|
Loadout, Mass, MountState, Mounting, Ori, Player, Pos,
|
||||||
Scale, Stats, Sticky, Vel,
|
Scale, Stats, Sticky, Vel,
|
||||||
},
|
},
|
||||||
msg::EcsCompPacket,
|
msg::EcsCompPacket,
|
||||||
@ -45,7 +45,6 @@ pub struct TrackedComps<'a> {
|
|||||||
pub energy: ReadStorage<'a, Energy>,
|
pub energy: ReadStorage<'a, Energy>,
|
||||||
pub can_build: ReadStorage<'a, CanBuild>,
|
pub can_build: ReadStorage<'a, CanBuild>,
|
||||||
pub light_emitter: ReadStorage<'a, LightEmitter>,
|
pub light_emitter: ReadStorage<'a, LightEmitter>,
|
||||||
pub particle_emitter: ReadStorage<'a, ParticleEmitters>,
|
|
||||||
pub item: ReadStorage<'a, Item>,
|
pub item: ReadStorage<'a, Item>,
|
||||||
pub scale: ReadStorage<'a, Scale>,
|
pub scale: ReadStorage<'a, Scale>,
|
||||||
pub mounting: ReadStorage<'a, Mounting>,
|
pub mounting: ReadStorage<'a, Mounting>,
|
||||||
@ -94,10 +93,6 @@ impl<'a> TrackedComps<'a> {
|
|||||||
.get(entity)
|
.get(entity)
|
||||||
.copied()
|
.copied()
|
||||||
.map(|c| comps.push(c.into()));
|
.map(|c| comps.push(c.into()));
|
||||||
self.particle_emitter
|
|
||||||
.get(entity)
|
|
||||||
.cloned()
|
|
||||||
.map(|c| comps.push(c.into()));
|
|
||||||
self.item.get(entity).cloned().map(|c| comps.push(c.into()));
|
self.item.get(entity).cloned().map(|c| comps.push(c.into()));
|
||||||
self.scale
|
self.scale
|
||||||
.get(entity)
|
.get(entity)
|
||||||
@ -153,7 +148,6 @@ pub struct ReadTrackers<'a> {
|
|||||||
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
|
pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
|
||||||
pub can_build: ReadExpect<'a, UpdateTracker<CanBuild>>,
|
pub can_build: ReadExpect<'a, UpdateTracker<CanBuild>>,
|
||||||
pub light_emitter: ReadExpect<'a, UpdateTracker<LightEmitter>>,
|
pub light_emitter: ReadExpect<'a, UpdateTracker<LightEmitter>>,
|
||||||
pub particle_emitter: ReadExpect<'a, UpdateTracker<ParticleEmitters>>,
|
|
||||||
pub item: ReadExpect<'a, UpdateTracker<Item>>,
|
pub item: ReadExpect<'a, UpdateTracker<Item>>,
|
||||||
pub scale: ReadExpect<'a, UpdateTracker<Scale>>,
|
pub scale: ReadExpect<'a, UpdateTracker<Scale>>,
|
||||||
pub mounting: ReadExpect<'a, UpdateTracker<Mounting>>,
|
pub mounting: ReadExpect<'a, UpdateTracker<Mounting>>,
|
||||||
@ -187,12 +181,6 @@ impl<'a> ReadTrackers<'a> {
|
|||||||
&comps.light_emitter,
|
&comps.light_emitter,
|
||||||
filter,
|
filter,
|
||||||
)
|
)
|
||||||
.with_component(
|
|
||||||
&comps.uid,
|
|
||||||
&*self.particle_emitter,
|
|
||||||
&comps.particle_emitter,
|
|
||||||
filter,
|
|
||||||
)
|
|
||||||
.with_component(&comps.uid, &*self.item, &comps.item, filter)
|
.with_component(&comps.uid, &*self.item, &comps.item, filter)
|
||||||
.with_component(&comps.uid, &*self.scale, &comps.scale, filter)
|
.with_component(&comps.uid, &*self.scale, &comps.scale, filter)
|
||||||
.with_component(&comps.uid, &*self.mounting, &comps.mounting, filter)
|
.with_component(&comps.uid, &*self.mounting, &comps.mounting, filter)
|
||||||
@ -223,7 +211,6 @@ pub struct WriteTrackers<'a> {
|
|||||||
energy: WriteExpect<'a, UpdateTracker<Energy>>,
|
energy: WriteExpect<'a, UpdateTracker<Energy>>,
|
||||||
can_build: WriteExpect<'a, UpdateTracker<CanBuild>>,
|
can_build: WriteExpect<'a, UpdateTracker<CanBuild>>,
|
||||||
light_emitter: WriteExpect<'a, UpdateTracker<LightEmitter>>,
|
light_emitter: WriteExpect<'a, UpdateTracker<LightEmitter>>,
|
||||||
particle_emitter: WriteExpect<'a, UpdateTracker<ParticleEmitters>>,
|
|
||||||
item: WriteExpect<'a, UpdateTracker<Item>>,
|
item: WriteExpect<'a, UpdateTracker<Item>>,
|
||||||
scale: WriteExpect<'a, UpdateTracker<Scale>>,
|
scale: WriteExpect<'a, UpdateTracker<Scale>>,
|
||||||
mounting: WriteExpect<'a, UpdateTracker<Mounting>>,
|
mounting: WriteExpect<'a, UpdateTracker<Mounting>>,
|
||||||
@ -246,9 +233,6 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
|
|||||||
trackers.energy.record_changes(&comps.energy);
|
trackers.energy.record_changes(&comps.energy);
|
||||||
trackers.can_build.record_changes(&comps.can_build);
|
trackers.can_build.record_changes(&comps.can_build);
|
||||||
trackers.light_emitter.record_changes(&comps.light_emitter);
|
trackers.light_emitter.record_changes(&comps.light_emitter);
|
||||||
trackers
|
|
||||||
.particle_emitter
|
|
||||||
.record_changes(&comps.particle_emitter);
|
|
||||||
trackers.item.record_changes(&comps.item);
|
trackers.item.record_changes(&comps.item);
|
||||||
trackers.scale.record_changes(&comps.scale);
|
trackers.scale.record_changes(&comps.scale);
|
||||||
trackers.mounting.record_changes(&comps.mounting);
|
trackers.mounting.record_changes(&comps.mounting);
|
||||||
@ -304,7 +288,6 @@ pub fn register_trackers(world: &mut World) {
|
|||||||
world.register_tracker::<Energy>();
|
world.register_tracker::<Energy>();
|
||||||
world.register_tracker::<CanBuild>();
|
world.register_tracker::<CanBuild>();
|
||||||
world.register_tracker::<LightEmitter>();
|
world.register_tracker::<LightEmitter>();
|
||||||
world.register_tracker::<ParticleEmitters>();
|
|
||||||
world.register_tracker::<Item>();
|
world.register_tracker::<Item>();
|
||||||
world.register_tracker::<Scale>();
|
world.register_tracker::<Scale>();
|
||||||
world.register_tracker::<Mounting>();
|
world.register_tracker::<Mounting>();
|
||||||
|
@ -2,7 +2,6 @@ use super::{
|
|||||||
super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt},
|
super::{Pipeline, TgtColorFmt, TgtDepthStencilFmt},
|
||||||
Globals, Light, Shadow,
|
Globals, Light, Shadow,
|
||||||
};
|
};
|
||||||
use common::comp::visual::ParticleEmitterMode;
|
|
||||||
use gfx::{
|
use gfx::{
|
||||||
self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner,
|
self, gfx_defines, gfx_impl_struct_meta, gfx_pipeline, gfx_pipeline_inner,
|
||||||
gfx_vertex_struct_meta,
|
gfx_vertex_struct_meta,
|
||||||
@ -22,15 +21,26 @@ gfx_defines! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vertex Instance {
|
vertex Instance {
|
||||||
|
// created_at time, so we can calculate time relativity, needed for relative animation.
|
||||||
|
// can save 32 bits per instance, for particles that are not relatively animated.
|
||||||
|
inst_time: f32 = "inst_time",
|
||||||
|
|
||||||
|
// a seed value for randomness
|
||||||
|
inst_entropy: f32 = "inst_entropy",
|
||||||
|
|
||||||
|
// modes should probably be seperate shaders, as a part of scaling and optimisation efforts
|
||||||
|
inst_mode: i32 = "inst_mode",
|
||||||
|
|
||||||
|
// a triangle is: f32 x 3 x 3 x 1 = 288 bits
|
||||||
|
// a quad is: f32 x 3 x 3 x 2 = 576 bits
|
||||||
|
// a cube is: f32 x 3 x 3 x 12 = 3456 bits
|
||||||
|
// this matrix is: f32 x 4 x 4 x 1 = 512 bits (per instance!)
|
||||||
|
// consider using vertex postion & entropy instead;
|
||||||
|
// to determine initial offset, scale, orientation etc.
|
||||||
inst_mat0: [f32; 4] = "inst_mat0",
|
inst_mat0: [f32; 4] = "inst_mat0",
|
||||||
inst_mat1: [f32; 4] = "inst_mat1",
|
inst_mat1: [f32; 4] = "inst_mat1",
|
||||||
inst_mat2: [f32; 4] = "inst_mat2",
|
inst_mat2: [f32; 4] = "inst_mat2",
|
||||||
inst_mat3: [f32; 4] = "inst_mat3",
|
inst_mat3: [f32; 4] = "inst_mat3",
|
||||||
inst_col: [f32; 3] = "inst_col",
|
|
||||||
inst_vel: [f32; 3] = "inst_vel",
|
|
||||||
inst_time: [f32; 4] = "inst_time",
|
|
||||||
inst_wind_sway: f32 = "inst_wind_sway",
|
|
||||||
mode: u8 = "mode",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline pipe {
|
pipeline pipe {
|
||||||
@ -69,43 +79,38 @@ impl Vertex {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ParticleMode {
|
||||||
|
CampfireSmoke,
|
||||||
|
CampfireFire,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ParticleMode {
|
||||||
|
pub fn into_uint(self) -> u32 { self as u32 }
|
||||||
|
}
|
||||||
|
|
||||||
impl Instance {
|
impl Instance {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
mat: Mat4<f32>,
|
inst_time: f64,
|
||||||
col: Rgb<f32>,
|
inst_entropy: f32,
|
||||||
vel: Vec3<f32>,
|
inst_mode: ParticleMode,
|
||||||
time: f64,
|
inst_mat: Mat4<f32>,
|
||||||
wind_sway: f32,
|
|
||||||
mode: ParticleEmitterMode,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mat_arr = mat.into_col_arrays();
|
let inst_mat_col = inst_mat.into_col_arrays();
|
||||||
Self {
|
Self {
|
||||||
inst_mat0: mat_arr[0],
|
inst_time: inst_time as f32,
|
||||||
inst_mat1: mat_arr[1],
|
inst_entropy,
|
||||||
inst_mat2: mat_arr[2],
|
inst_mode: inst_mode as i32,
|
||||||
inst_mat3: mat_arr[3],
|
|
||||||
inst_col: col.into_array(),
|
|
||||||
inst_vel: vel.into_array(),
|
|
||||||
inst_time: [time as f32; 4],
|
|
||||||
|
|
||||||
inst_wind_sway: wind_sway,
|
inst_mat0: inst_mat_col[0],
|
||||||
|
inst_mat1: inst_mat_col[1],
|
||||||
mode: mode as u8,
|
inst_mat2: inst_mat_col[2],
|
||||||
|
inst_mat3: inst_mat_col[3],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Instance {
|
impl Default for Instance {
|
||||||
fn default() -> Self {
|
fn default() -> Self { Self::new(0.0, 0.0, ParticleMode::CampfireSmoke, Mat4::identity()) }
|
||||||
Self::new(
|
|
||||||
Mat4::identity(),
|
|
||||||
Rgb::broadcast(1.0),
|
|
||||||
Vec3::zero(),
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
ParticleEmitterMode::Sprinkler,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ParticlePipeline;
|
pub struct ParticlePipeline;
|
||||||
|
@ -398,14 +398,7 @@ impl Scene {
|
|||||||
self.figure_mgr.clean(scene_data.tick);
|
self.figure_mgr.clean(scene_data.tick);
|
||||||
|
|
||||||
// Maintain the particles.
|
// Maintain the particles.
|
||||||
self.particle_mgr.maintain(
|
self.particle_mgr.maintain(renderer, &scene_data);
|
||||||
renderer,
|
|
||||||
&scene_data,
|
|
||||||
self.camera.get_focus_pos(),
|
|
||||||
self.loaded_distance,
|
|
||||||
view_mat,
|
|
||||||
proj_mat,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Maintain audio
|
// Maintain audio
|
||||||
self.sfx_mgr
|
self.sfx_mgr
|
||||||
@ -442,13 +435,8 @@ impl Scene {
|
|||||||
scene_data.figure_lod_render_distance,
|
scene_data.figure_lod_render_distance,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.particle_mgr.render(
|
self.particle_mgr
|
||||||
renderer,
|
.render(renderer, &self.globals, &self.lights, &self.shadows);
|
||||||
&self.globals,
|
|
||||||
&self.lights,
|
|
||||||
&self.shadows,
|
|
||||||
self.camera.get_focus_pos(),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Render the skybox.
|
// Render the skybox.
|
||||||
renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals);
|
renderer.render_skybox(&self.skybox.model, &self.globals, &self.skybox.locals);
|
||||||
|
@ -2,51 +2,31 @@ use super::SceneData;
|
|||||||
use crate::{
|
use crate::{
|
||||||
mesh::Meshable,
|
mesh::Meshable,
|
||||||
render::{
|
render::{
|
||||||
mesh::Quad, Consts, Globals, Instances, Light, Model, ParticleInstance, ParticlePipeline,
|
pipelines::particle::ParticleMode, Consts, Globals, Instances, Light, Model,
|
||||||
Renderer, Shadow,
|
ParticleInstance, ParticlePipeline, Renderer, Shadow,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
assets,
|
assets,
|
||||||
comp::{
|
comp::{object, Body, CharacterState, Pos},
|
||||||
visual::ParticleEmitterMode, CharacterState, Ori, ParticleEmitter, ParticleEmitters, Pos,
|
|
||||||
Vel,
|
|
||||||
},
|
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
};
|
};
|
||||||
use dot_vox::DotVoxData;
|
use dot_vox::DotVoxData;
|
||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use specs::{Entity as EcsEntity, Join, WorldExt};
|
use specs::{Join, WorldExt};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use vek::{Mat4, Rgb, Vec3};
|
use vek::{Mat4, Vec3};
|
||||||
|
|
||||||
struct Particles {
|
struct Particles {
|
||||||
// this is probably nieve,
|
|
||||||
// could cache and re-use between particles,
|
|
||||||
// should be a cache key?
|
|
||||||
// model: Model<ParticlePipeline>,
|
|
||||||
// created_at: Instant,
|
|
||||||
// lifespan: Duration,
|
|
||||||
alive_until: Instant, // created_at + lifespan
|
alive_until: Instant, // created_at + lifespan
|
||||||
|
|
||||||
instances: Instances<ParticleInstance>,
|
instances: Instances<ParticleInstance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Emitter {
|
|
||||||
last_emit: Instant,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ParticleMgr {
|
pub struct ParticleMgr {
|
||||||
// to keep track of spawn intervals
|
// keep track of lifespans
|
||||||
emitters: HashMap<EcsEntity, Emitter>,
|
|
||||||
|
|
||||||
// to keep track of lifespans
|
|
||||||
particles: Vec<Particles>,
|
particles: Vec<Particles>,
|
||||||
|
|
||||||
model_cache: HashMap<&'static str, Model<ParticlePipeline>>,
|
model_cache: HashMap<&'static str, Model<ParticlePipeline>>,
|
||||||
|
|
||||||
beginning_of_time: Instant,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const MODEL_KEY: &str = "voxygen.voxel.particle";
|
const MODEL_KEY: &str = "voxygen.voxel.particle";
|
||||||
@ -55,21 +35,18 @@ impl ParticleMgr {
|
|||||||
pub fn new(renderer: &mut Renderer) -> Self {
|
pub fn new(renderer: &mut Renderer) -> Self {
|
||||||
let mut model_cache = HashMap::new();
|
let mut model_cache = HashMap::new();
|
||||||
|
|
||||||
let model = model_cache.entry(MODEL_KEY).or_insert_with(|| {
|
model_cache.entry(MODEL_KEY).or_insert_with(|| {
|
||||||
let offset = Vec3::zero();
|
let offset = Vec3::zero();
|
||||||
let lod_scale = Vec3::one();
|
let lod_scale = Vec3::one();
|
||||||
|
|
||||||
// TODO: from cache
|
|
||||||
let vox = assets::load_expect::<DotVoxData>(MODEL_KEY);
|
let vox = assets::load_expect::<DotVoxData>(MODEL_KEY);
|
||||||
|
|
||||||
// TODO: from cache
|
|
||||||
let mesh = &Meshable::<ParticlePipeline, ParticlePipeline>::generate_mesh(
|
let mesh = &Meshable::<ParticlePipeline, ParticlePipeline>::generate_mesh(
|
||||||
&Segment::from(vox.as_ref()),
|
&Segment::from(vox.as_ref()),
|
||||||
(offset * lod_scale, Vec3::one() / lod_scale),
|
(offset * lod_scale, Vec3::one() / lod_scale),
|
||||||
)
|
)
|
||||||
.0;
|
.0;
|
||||||
|
|
||||||
// TODO: from cache
|
|
||||||
let model = renderer
|
let model = renderer
|
||||||
.create_model(mesh)
|
.create_model(mesh)
|
||||||
.expect("Failed to create particle model");
|
.expect("Failed to create particle model");
|
||||||
@ -78,137 +55,103 @@ impl ParticleMgr {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
emitters: HashMap::new(),
|
|
||||||
particles: Vec::new(),
|
particles: Vec::new(),
|
||||||
model_cache,
|
model_cache,
|
||||||
beginning_of_time: Instant::now(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maintain(
|
pub fn maintain(&mut self, renderer: &mut Renderer, scene_data: &SceneData) {
|
||||||
&mut self,
|
|
||||||
renderer: &mut Renderer,
|
|
||||||
scene_data: &SceneData,
|
|
||||||
focus_pos: Vec3<f32>,
|
|
||||||
loaded_distance: f32,
|
|
||||||
view_mat: Mat4<f32>,
|
|
||||||
proj_mat: Mat4<f32>,
|
|
||||||
) {
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let state = scene_data.state;
|
|
||||||
let ecs = state.ecs();
|
|
||||||
|
|
||||||
// remove dead emitters
|
|
||||||
self.emitters.retain(|k, _v| ecs.is_alive(*k));
|
|
||||||
|
|
||||||
// remove dead particles
|
// remove dead particles
|
||||||
self.particles.retain(|p| p.alive_until > now);
|
self.particles.retain(|p| p.alive_until > now);
|
||||||
|
|
||||||
// add ParticleEmitter particles
|
self.maintain_waypoint_particles(renderer, scene_data);
|
||||||
self.maintain_particle_emitter(renderer, scene_data);
|
|
||||||
|
|
||||||
self.maintain_ability_particles(renderer, scene_data);
|
self.maintain_boost_particles(renderer, scene_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maintain_particle_emitter(&mut self, renderer: &mut Renderer, scene_data: &SceneData) {
|
fn maintain_waypoint_particles(&mut self, renderer: &mut Renderer, scene_data: &SceneData) {
|
||||||
let state = scene_data.state;
|
let state = scene_data.state;
|
||||||
let ecs = state.ecs();
|
let ecs = state.ecs();
|
||||||
|
|
||||||
let time = state.get_time();
|
let time = state.get_time();
|
||||||
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let beginning_of_time1 = self.beginning_of_time.clone();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
for (_i, (entity, particle_emitters, pos, ori, vel)) in (
|
for (_i, (_entity, pos, body)) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<ParticleEmitters>(),
|
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
ecs.read_storage::<Ori>().maybe(),
|
&ecs.read_storage::<Body>(),
|
||||||
ecs.read_storage::<Vel>().maybe(),
|
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
for particle_emitter in &particle_emitters.0 {
|
match body {
|
||||||
// TODO: track multiple particle_emitter last_emit
|
Body::Object(object::Body::CampfireLit) => {
|
||||||
let emitter = self.emitters.entry(entity).or_insert_with(|| Emitter {
|
let fire_cpu_insts = vec![ParticleInstance::new(
|
||||||
last_emit: beginning_of_time1, // self.beginning_of_time.clone()
|
time,
|
||||||
|
rng.gen(),
|
||||||
|
ParticleMode::CampfireFire,
|
||||||
|
Mat4::identity().translated_3d(pos.0),
|
||||||
|
)];
|
||||||
|
|
||||||
|
self.particles.push(Particles {
|
||||||
|
alive_until: now + Duration::from_millis(250),
|
||||||
|
instances: renderer
|
||||||
|
.create_instances(&fire_cpu_insts)
|
||||||
|
.expect("Failed to upload particle instances to the GPU!"),
|
||||||
});
|
});
|
||||||
|
|
||||||
if emitter.last_emit + particle_emitter.frequency < now {
|
let smoke_cpu_insts = vec![ParticleInstance::new(
|
||||||
emitter.last_emit = Instant::now();
|
time,
|
||||||
|
rng.gen(),
|
||||||
|
ParticleMode::CampfireSmoke,
|
||||||
|
Mat4::identity().translated_3d(pos.0),
|
||||||
|
)];
|
||||||
|
|
||||||
let cpu_insts =
|
let smoke_cpu_insts = renderer
|
||||||
into_particle_instances(&particle_emitter, renderer, time, pos, ori, vel);
|
.create_instances(&smoke_cpu_insts)
|
||||||
|
|
||||||
let gpu_insts = renderer
|
|
||||||
.create_instances(&cpu_insts)
|
|
||||||
.expect("Failed to upload particle instances to the GPU!");
|
.expect("Failed to upload particle instances to the GPU!");
|
||||||
|
|
||||||
let entry = self.particles.push(Particles {
|
self.particles.push(Particles {
|
||||||
alive_until: now + particle_emitter.initial_lifespan,
|
alive_until: now + Duration::from_secs(10),
|
||||||
instances: gpu_insts,
|
instances: smoke_cpu_insts,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maintain_ability_particles(&mut self, renderer: &mut Renderer, scene_data: &SceneData) {
|
fn maintain_boost_particles(&mut self, renderer: &mut Renderer, scene_data: &SceneData) {
|
||||||
let state = scene_data.state;
|
let state = scene_data.state;
|
||||||
let ecs = state.ecs();
|
let ecs = state.ecs();
|
||||||
|
|
||||||
let time = state.get_time();
|
let time = state.get_time();
|
||||||
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let beginning_of_time1 = self.beginning_of_time.clone();
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
for (_i, (entity, pos, character_state)) in (
|
for (_i, (_entity, pos, character_state)) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
//&ecs.read_storage::<ParticleEmitter>(),
|
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
&ecs.read_storage::<CharacterState>(),
|
&ecs.read_storage::<CharacterState>(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
// let emitter = self.emitters.entry(entity).or_insert_with(|| Emitter {
|
if let CharacterState::Boost(_) = character_state {
|
||||||
// last_emit: beginning_of_time1, // self.beginning_of_time.clone()
|
let cpu_insts = vec![ParticleInstance::new(
|
||||||
// });
|
time,
|
||||||
|
rng.gen(),
|
||||||
// if emitter.last_emit + particle_emitter.frequency < now {
|
ParticleMode::CampfireSmoke,
|
||||||
// emitter.last_emit = Instant::now();
|
Mat4::identity().translated_3d(pos.0),
|
||||||
// }
|
)];
|
||||||
|
|
||||||
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 */
|
|
||||||
),
|
|
||||||
initial_col: (Rgb::zero(), Rgb::one()),
|
|
||||||
};
|
|
||||||
|
|
||||||
let cpu_insts =
|
|
||||||
into_particle_instances(&particle_emitter, renderer, time, pos, None, None);
|
|
||||||
|
|
||||||
let gpu_insts = renderer
|
let gpu_insts = renderer
|
||||||
.create_instances(&cpu_insts)
|
.create_instances(&cpu_insts)
|
||||||
.expect("Failed to upload particle instances to the GPU!");
|
.expect("Failed to upload particle instances to the GPU!");
|
||||||
|
|
||||||
let entry = self.particles.push(Particles {
|
self.particles.push(Particles {
|
||||||
alive_until: now + particle_emitter.initial_lifespan,
|
alive_until: now + Duration::from_secs(15),
|
||||||
instances: gpu_insts,
|
instances: gpu_insts,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -221,7 +164,6 @@ impl ParticleMgr {
|
|||||||
globals: &Consts<Globals>,
|
globals: &Consts<Globals>,
|
||||||
lights: &Consts<Light>,
|
lights: &Consts<Light>,
|
||||||
shadows: &Consts<Shadow>,
|
shadows: &Consts<Shadow>,
|
||||||
focus_pos: Vec3<f32>,
|
|
||||||
) {
|
) {
|
||||||
for particle in &self.particles {
|
for particle in &self.particles {
|
||||||
renderer.render_particles(
|
renderer.render_particles(
|
||||||
@ -237,58 +179,3 @@ impl ParticleMgr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_particle_instances(
|
|
||||||
particle_emitter: &ParticleEmitter,
|
|
||||||
renderer: &mut Renderer,
|
|
||||||
time: f64,
|
|
||||||
pos: &Pos,
|
|
||||||
ori: Option<&Ori>,
|
|
||||||
vel: Option<&Vel>,
|
|
||||||
) -> Vec<ParticleInstance> {
|
|
||||||
let mut rng = rand::thread_rng();
|
|
||||||
let vel_default = Vel::default();
|
|
||||||
let vel2 = vel.unwrap_or_else(|| &vel_default).0;
|
|
||||||
|
|
||||||
let mut instances_vec = Vec::new();
|
|
||||||
|
|
||||||
for x in 0..rng.gen_range(particle_emitter.count.0, particle_emitter.count.1) {
|
|
||||||
// how does ParticleEmitterMode fit in here?
|
|
||||||
// can we have a ParticleInstance type per ParticleEmitterMode?
|
|
||||||
// can we mix and match instance types in the same instances_vec?
|
|
||||||
instances_vec.push(ParticleInstance::new(
|
|
||||||
Mat4::identity()
|
|
||||||
// initial rotation
|
|
||||||
.rotated_x(rng.gen_range(particle_emitter.initial_orientation.0.x * std::f32::consts::PI * 2.0, particle_emitter.initial_orientation.1.x * std::f32::consts::PI * 2.0))
|
|
||||||
.rotated_y(rng.gen_range(particle_emitter.initial_orientation.0.y * std::f32::consts::PI * 2.0, particle_emitter.initial_orientation.1.y * std::f32::consts::PI * 2.0))
|
|
||||||
.rotated_z(rng.gen_range(particle_emitter.initial_orientation.0.z * std::f32::consts::PI * 2.0, particle_emitter.initial_orientation.1.z * std::f32::consts::PI * 2.0))
|
|
||||||
// initial scale
|
|
||||||
.scaled_3d(rng.gen_range(particle_emitter.initial_scale.0, particle_emitter.initial_scale.1))
|
|
||||||
// inition position
|
|
||||||
.translated_3d(
|
|
||||||
pos.0 // relative
|
|
||||||
+ Vec3::new(
|
|
||||||
rng.gen_range(particle_emitter.initial_offset.0.x, particle_emitter.initial_offset.1.x),
|
|
||||||
rng.gen_range(particle_emitter.initial_offset.0.y, particle_emitter.initial_offset.1.y),
|
|
||||||
rng.gen_range(particle_emitter.initial_offset.0.z, particle_emitter.initial_offset.1.z),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Rgb::new(
|
|
||||||
rng.gen_range(particle_emitter.initial_col.0.r, particle_emitter.initial_col.1.r),
|
|
||||||
rng.gen_range(particle_emitter.initial_col.0.g, particle_emitter.initial_col.1.g),
|
|
||||||
rng.gen_range(particle_emitter.initial_col.0.b, particle_emitter.initial_col.1.b),
|
|
||||||
), // instance color
|
|
||||||
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 */
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
instances_vec
|
|
||||||
}
|
|
||||||
|
@ -1003,7 +1003,10 @@ impl PlayState for SessionState {
|
|||||||
mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable,
|
mouse_smoothing: global_state.settings.gameplay.smooth_pan_enable,
|
||||||
sprite_render_distance: global_state.settings.graphics.sprite_render_distance
|
sprite_render_distance: global_state.settings.graphics.sprite_render_distance
|
||||||
as f32,
|
as f32,
|
||||||
particle_render_distance: global_state.settings.graphics.particle_render_distance
|
particle_render_distance: global_state
|
||||||
|
.settings
|
||||||
|
.graphics
|
||||||
|
.particle_render_distance
|
||||||
as f32,
|
as f32,
|
||||||
figure_lod_render_distance: global_state
|
figure_lod_render_distance: global_state
|
||||||
.settings
|
.settings
|
||||||
@ -1060,6 +1063,7 @@ impl PlayState for SessionState {
|
|||||||
mouse_smoothing: settings.gameplay.smooth_pan_enable,
|
mouse_smoothing: settings.gameplay.smooth_pan_enable,
|
||||||
sprite_render_distance: settings.graphics.sprite_render_distance as f32,
|
sprite_render_distance: settings.graphics.sprite_render_distance as f32,
|
||||||
figure_lod_render_distance: settings.graphics.figure_lod_render_distance as f32,
|
figure_lod_render_distance: settings.graphics.figure_lod_render_distance as f32,
|
||||||
|
particle_render_distance: settings.graphics.particle_render_distance as f32,
|
||||||
is_aiming: self.is_aiming,
|
is_aiming: self.is_aiming,
|
||||||
};
|
};
|
||||||
self.scene.render(
|
self.scene.render(
|
||||||
|
Loading…
Reference in New Issue
Block a user