mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Glider vortices PoC particle effects
This commit is contained in:
parent
34d264c413
commit
07dda3be22
@ -72,6 +72,7 @@ const int WATER = 30;
|
|||||||
const int ICE_SPIKES = 31;
|
const int ICE_SPIKES = 31;
|
||||||
const int DRIP = 32;
|
const int DRIP = 32;
|
||||||
const int TORNADO = 33;
|
const int TORNADO = 33;
|
||||||
|
const int VORTEX = 34;
|
||||||
|
|
||||||
// meters per second squared (acceleration)
|
// meters per second squared (acceleration)
|
||||||
const float earth_gravity = 9.807;
|
const float earth_gravity = 9.807;
|
||||||
@ -553,6 +554,29 @@ void main() {
|
|||||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case VORTEX:
|
||||||
|
f_reflect = 1.0;
|
||||||
|
float mag = length(inst_dir);
|
||||||
|
float s = 4 * start_end(max(0, slow_start(2.0) - 0.3), 0);
|
||||||
|
float r = 0.2 * (pow(1 * rand0, 2) + pow(rand1 * 2, 2) + pow(rand2 * 4, 2));
|
||||||
|
attr = Attr(
|
||||||
|
spiral_motion(
|
||||||
|
s * normalize(inst_dir) * mag,
|
||||||
|
0.5 * max(0, slow_start(2.0) - 0.3) * max(0, floor(0.5 * r - 0.5)) * min(linear_scale(10), 1),
|
||||||
|
lifetime / (20.0 * inst_lifespan),
|
||||||
|
0.4 * r,
|
||||||
|
1.1 * inst_time * (length(inst_dir))
|
||||||
|
),
|
||||||
|
vec3(
|
||||||
|
(1.0 - 0.5 * abs(r))
|
||||||
|
* (1.5 + 0.5 * sin(tick.x * 10 - lifetime * 10))
|
||||||
|
* max(0, mag - 12) * s
|
||||||
|
* 0.02
|
||||||
|
),
|
||||||
|
vec4(vec3(1, 1, 1), 1),
|
||||||
|
spin_in_axis(inst_dir, tick.z)
|
||||||
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
attr = Attr(
|
attr = Attr(
|
||||||
linear_motion(
|
linear_motion(
|
||||||
|
@ -232,7 +232,7 @@ pub fn angle_of_attack(ori: &Ori, rel_flow_dir: &Dir) -> f32 {
|
|||||||
|
|
||||||
/// Total lift coefficient for a finite wing of symmetric aerofoil shape and
|
/// Total lift coefficient for a finite wing of symmetric aerofoil shape and
|
||||||
/// elliptical pressure distribution. (Multiplied by reference area.)
|
/// elliptical pressure distribution. (Multiplied by reference area.)
|
||||||
fn lift_coefficient(
|
pub fn lift_coefficient(
|
||||||
planform_area: f32,
|
planform_area: f32,
|
||||||
angle_of_attack: f32,
|
angle_of_attack: f32,
|
||||||
lift_slope: f32,
|
lift_slope: f32,
|
||||||
@ -355,7 +355,7 @@ impl WingShape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Induced drag coefficient (drag due to lift)
|
/// Induced drag coefficient (drag due to lift)
|
||||||
fn induced_drag_coefficient(aspect_ratio: f32, lift_coefficient: f32) -> f32 {
|
pub fn induced_drag_coefficient(aspect_ratio: f32, lift_coefficient: f32) -> f32 {
|
||||||
let ar = aspect_ratio;
|
let ar = aspect_ratio;
|
||||||
if ar > 25.0 {
|
if ar > 25.0 {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
comp::{
|
comp::{
|
||||||
fluid_dynamics::{Drag, Glide, WingShape},
|
fluid_dynamics::{Drag, Glide, WingShape},
|
||||||
Ori,
|
Body, Ori, Pos,
|
||||||
},
|
},
|
||||||
util::Dir,
|
util::Dir,
|
||||||
};
|
};
|
||||||
@ -17,6 +17,7 @@ pub struct Glider {
|
|||||||
pub wing_shape: WingShape,
|
pub wing_shape: WingShape,
|
||||||
pub planform_area: f32,
|
pub planform_area: f32,
|
||||||
pub ori: Ori,
|
pub ori: Ori,
|
||||||
|
span_length: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Glider {
|
impl Glider {
|
||||||
@ -32,10 +33,24 @@ impl Glider {
|
|||||||
Self {
|
Self {
|
||||||
wing_shape: WingShape::Elliptical { aspect_ratio },
|
wing_shape: WingShape::Elliptical { aspect_ratio },
|
||||||
planform_area,
|
planform_area,
|
||||||
|
span_length,
|
||||||
ori,
|
ori,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn pos(&self, pilot: (&Pos, &Ori, &Body)) -> Pos {
|
||||||
|
let height = pilot.2.dimensions().z;
|
||||||
|
let cg = Vec3::unit_z() * height * tweak!(0.7);
|
||||||
|
let pos_from_cg = *pilot.1.up() * height * tweak!(0.5);
|
||||||
|
Pos(pilot.0.0 + cg + pos_from_cg)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wing_tips(&self, pilot: (&Pos, &Ori, &Body)) -> (Pos, Pos) {
|
||||||
|
let right = tweak!(0.65) * *self.ori.right() * self.span_length / 2.0;
|
||||||
|
let pos = self.pos(pilot).0;
|
||||||
|
(Pos(pos - right), Pos(pos + right))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn roll(&mut self, angle_right: f32) { self.ori = self.ori.rolled_right(angle_right); }
|
pub fn roll(&mut self, angle_right: f32) { self.ori = self.ori.rolled_right(angle_right); }
|
||||||
|
|
||||||
pub fn pitch(&mut self, angle_up: f32) { self.ori = self.ori.pitched_up(angle_up); }
|
pub fn pitch(&mut self, angle_up: f32) { self.ori = self.ori.pitched_up(angle_up); }
|
||||||
|
@ -84,6 +84,7 @@ pub enum ParticleMode {
|
|||||||
IceSpikes = 31,
|
IceSpikes = 31,
|
||||||
Drip = 32,
|
Drip = 32,
|
||||||
Tornado = 33,
|
Tornado = 33,
|
||||||
|
Vortex = 34,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParticleMode {
|
impl ParticleMode {
|
||||||
|
@ -9,8 +9,10 @@ use crate::{
|
|||||||
use common::{
|
use common::{
|
||||||
assets::{AssetExt, DotVoxAsset},
|
assets::{AssetExt, DotVoxAsset},
|
||||||
comp::{
|
comp::{
|
||||||
self, aura, beam, body, buff, item::Reagent, object, shockwave, BeamSegment, Body,
|
self, aura, beam, body, buff,
|
||||||
CharacterState, Ori, Pos, Shockwave, Vel,
|
fluid_dynamics::{angle_of_attack, induced_drag_coefficient, lift_coefficient, Glide},
|
||||||
|
item::Reagent,
|
||||||
|
object, shockwave, BeamSegment, Body, CharacterState, Ori, Pos, Shockwave, Vel,
|
||||||
},
|
},
|
||||||
figure::Segment,
|
figure::Segment,
|
||||||
outcome::Outcome,
|
outcome::Outcome,
|
||||||
@ -18,6 +20,7 @@ use common::{
|
|||||||
spiral::Spiral2d,
|
spiral::Spiral2d,
|
||||||
states::{self, utils::StageSection},
|
states::{self, utils::StageSection},
|
||||||
terrain::TerrainChunk,
|
terrain::TerrainChunk,
|
||||||
|
util::Dir,
|
||||||
vol::{RectRasterableVol, SizedVol},
|
vol::{RectRasterableVol, SizedVol},
|
||||||
};
|
};
|
||||||
use common_base::span;
|
use common_base::span;
|
||||||
@ -561,16 +564,69 @@ impl ParticleMgr {
|
|||||||
let dt = scene_data.state.get_delta_time();
|
let dt = scene_data.state.get_delta_time();
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
for (entity, pos, vel, character_state, body) in (
|
for (entity, pos, vel, ori, character_state, body) in (
|
||||||
&ecs.entities(),
|
&ecs.entities(),
|
||||||
&ecs.read_storage::<Pos>(),
|
&ecs.read_storage::<Pos>(),
|
||||||
ecs.read_storage::<Vel>().maybe(),
|
ecs.read_storage::<Vel>().maybe(),
|
||||||
|
&ecs.read_storage::<Ori>(),
|
||||||
&ecs.read_storage::<CharacterState>(),
|
&ecs.read_storage::<CharacterState>(),
|
||||||
&ecs.read_storage::<Body>(),
|
&ecs.read_storage::<Body>(),
|
||||||
)
|
)
|
||||||
.join()
|
.join()
|
||||||
{
|
{
|
||||||
match character_state {
|
match character_state {
|
||||||
|
CharacterState::Glide(data) => {
|
||||||
|
let trail_tick_count =
|
||||||
|
33.max(self.scheduler.heartbeats(Duration::from_millis(1)));
|
||||||
|
let trail = ecs
|
||||||
|
.read_storage::<comp::PhysicsState>()
|
||||||
|
.get(entity)
|
||||||
|
.and_then(|physics| physics.in_fluid)
|
||||||
|
.and_then(|fluid| {
|
||||||
|
vel.map(|vel| (fluid.dynamic_pressure(vel), fluid.relative_flow(vel)))
|
||||||
|
})
|
||||||
|
.and_then(|(q, rel_flow)| {
|
||||||
|
Some(rel_flow.0.magnitude_squared())
|
||||||
|
.filter(|v_sq| v_sq > &std::f32::EPSILON)
|
||||||
|
.map(|v_sq| (q, Dir::new(rel_flow.0 / v_sq.sqrt())))
|
||||||
|
})
|
||||||
|
.map(|(q, flow_dir)| {
|
||||||
|
// hacky heuristic for vortex trails; they're nowhere near an accurate
|
||||||
|
// representation, but
|
||||||
|
// - it's sort of the right direction
|
||||||
|
// - it scales with induced drag (which is due to these vortices)
|
||||||
|
let wing_shape = data.glider.wing_shape();
|
||||||
|
let aoa = angle_of_attack(data.glider.ori(), &flow_dir);
|
||||||
|
let c_l = lift_coefficient(
|
||||||
|
data.glider.planform_area(),
|
||||||
|
aoa,
|
||||||
|
wing_shape.lift_slope(),
|
||||||
|
wing_shape.stall_angle(),
|
||||||
|
);
|
||||||
|
let c_d_i = induced_drag_coefficient(wing_shape.aspect_ratio(), c_l);
|
||||||
|
-q * *data.glider.ori().look_dir() * c_d_i.abs()
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
self.particles.reserve(trail_tick_count as usize);
|
||||||
|
for i in 0..trail_tick_count {
|
||||||
|
let (left_tip, right_tip) = data.glider.wing_tips((pos, ori, body));
|
||||||
|
self.particles.push(Particle::new_directed(
|
||||||
|
Duration::from_millis(300),
|
||||||
|
time + i as f64 / 1000.0,
|
||||||
|
ParticleMode::Vortex,
|
||||||
|
left_tip.0,
|
||||||
|
left_tip.0 + trail * 0.2,
|
||||||
|
));
|
||||||
|
self.particles.push(Particle::new_directed(
|
||||||
|
Duration::from_millis(300),
|
||||||
|
time + i as f64 / 1000.0,
|
||||||
|
ParticleMode::Vortex,
|
||||||
|
right_tip.0,
|
||||||
|
right_tip.0 + trail * 0.2,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
},
|
||||||
CharacterState::Boost(_) => {
|
CharacterState::Boost(_) => {
|
||||||
self.particles.resize_with(
|
self.particles.resize_with(
|
||||||
self.particles.len()
|
self.particles.len()
|
||||||
|
Loading…
Reference in New Issue
Block a user