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 DRIP = 32;
|
||||
const int TORNADO = 33;
|
||||
const int VORTEX = 34;
|
||||
|
||||
// meters per second squared (acceleration)
|
||||
const float earth_gravity = 9.807;
|
||||
@ -553,6 +554,29 @@ void main() {
|
||||
spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9)
|
||||
);
|
||||
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:
|
||||
attr = Attr(
|
||||
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
|
||||
/// elliptical pressure distribution. (Multiplied by reference area.)
|
||||
fn lift_coefficient(
|
||||
pub fn lift_coefficient(
|
||||
planform_area: f32,
|
||||
angle_of_attack: f32,
|
||||
lift_slope: f32,
|
||||
@ -355,7 +355,7 @@ impl WingShape {
|
||||
}
|
||||
|
||||
/// 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;
|
||||
if ar > 25.0 {
|
||||
tracing::warn!(
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
comp::{
|
||||
fluid_dynamics::{Drag, Glide, WingShape},
|
||||
Ori,
|
||||
Body, Ori, Pos,
|
||||
},
|
||||
util::Dir,
|
||||
};
|
||||
@ -17,6 +17,7 @@ pub struct Glider {
|
||||
pub wing_shape: WingShape,
|
||||
pub planform_area: f32,
|
||||
pub ori: Ori,
|
||||
span_length: f32,
|
||||
}
|
||||
|
||||
impl Glider {
|
||||
@ -32,10 +33,24 @@ impl Glider {
|
||||
Self {
|
||||
wing_shape: WingShape::Elliptical { aspect_ratio },
|
||||
planform_area,
|
||||
span_length,
|
||||
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 pitch(&mut self, angle_up: f32) { self.ori = self.ori.pitched_up(angle_up); }
|
||||
|
@ -84,6 +84,7 @@ pub enum ParticleMode {
|
||||
IceSpikes = 31,
|
||||
Drip = 32,
|
||||
Tornado = 33,
|
||||
Vortex = 34,
|
||||
}
|
||||
|
||||
impl ParticleMode {
|
||||
|
@ -9,8 +9,10 @@ use crate::{
|
||||
use common::{
|
||||
assets::{AssetExt, DotVoxAsset},
|
||||
comp::{
|
||||
self, aura, beam, body, buff, item::Reagent, object, shockwave, BeamSegment, Body,
|
||||
CharacterState, Ori, Pos, Shockwave, Vel,
|
||||
self, aura, beam, body, buff,
|
||||
fluid_dynamics::{angle_of_attack, induced_drag_coefficient, lift_coefficient, Glide},
|
||||
item::Reagent,
|
||||
object, shockwave, BeamSegment, Body, CharacterState, Ori, Pos, Shockwave, Vel,
|
||||
},
|
||||
figure::Segment,
|
||||
outcome::Outcome,
|
||||
@ -18,6 +20,7 @@ use common::{
|
||||
spiral::Spiral2d,
|
||||
states::{self, utils::StageSection},
|
||||
terrain::TerrainChunk,
|
||||
util::Dir,
|
||||
vol::{RectRasterableVol, SizedVol},
|
||||
};
|
||||
use common_base::span;
|
||||
@ -561,16 +564,69 @@ impl ParticleMgr {
|
||||
let dt = scene_data.state.get_delta_time();
|
||||
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.read_storage::<Pos>(),
|
||||
ecs.read_storage::<Vel>().maybe(),
|
||||
&ecs.read_storage::<Ori>(),
|
||||
&ecs.read_storage::<CharacterState>(),
|
||||
&ecs.read_storage::<Body>(),
|
||||
)
|
||||
.join()
|
||||
{
|
||||
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(_) => {
|
||||
self.particles.resize_with(
|
||||
self.particles.len()
|
||||
|
Loading…
Reference in New Issue
Block a user