Improve airflow particles

This commit is contained in:
juliancoffee 2024-02-01 15:59:41 +02:00
parent 16c41109d3
commit 1dee12af85
3 changed files with 84 additions and 27 deletions

View File

@ -164,10 +164,24 @@ mat4 spin_in_axis(vec3 axis, float angle)
float c = cos(angle); float c = cos(angle);
float oc = 1.0 - c; float oc = 1.0 - c;
return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0, return mat4(
oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0, oc * axis.x * axis.x + c,
oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0, oc * axis.x * axis.y - axis.z * s,
0, 0, 0, 1); oc * axis.z * axis.x + axis.y * s,
0,
oc * axis.x * axis.y + axis.z * s,
oc * axis.y * axis.y + c,
oc * axis.y * axis.z - axis.x * s,
0,
oc * axis.z * axis.x - axis.y * s,
oc * axis.y * axis.z + axis.x * s,
oc * axis.z * axis.z + c,
0,
0, 0, 0, 1
);
} }
mat4 identity() { mat4 identity() {
@ -986,11 +1000,19 @@ void main() {
); );
break; break;
case AIRFLOW: case AIRFLOW:
perp_axis = normalize(cross(inst_dir, vec3(0.0, 0.0, 1.0))); perp_axis = normalize(cross(inst_dir, vec3(1.0, 0.0, 0.0)));
attr = Attr( attr = Attr(
// offsets
inst_dir * 0.2 * length(inst_dir) * percent() + inst_dir * percent() * 0.08, inst_dir * 0.2 * length(inst_dir) * percent() + inst_dir * percent() * 0.08,
vec3(0.03 * length(inst_dir), 0.03 * length(inst_dir), 20.0 * length(inst_dir) * percent() * (1 - percent())), // scale
vec3(
0.3 * length(inst_dir),
0.3 * length(inst_dir),
3.0 * length(inst_dir) * percent() * (1 - percent())
),
// color
vec4(1.1, 1.1, 1.1, 0.3), vec4(1.1, 1.1, 1.1, 0.3),
// rotation
spin_in_axis(perp_axis, asin(inst_dir.z / length(inst_dir)) + PI / 2.0) spin_in_axis(perp_axis, asin(inst_dir.z / length(inst_dir)) + PI / 2.0)
); );
break; break;
@ -1018,7 +1040,14 @@ void main() {
// First 3 normals are negative, next 3 are positive // First 3 normals are negative, next 3 are positive
// TODO: Make particle normals match orientation // TODO: Make particle normals match orientation
vec4 normals[6] = vec4[](vec4(-1,0,0,0), vec4(1,0,0,0), vec4(0,-1,0,0), vec4(0,1,0,0), vec4(0,0,-1,0), vec4(0,0,1,0)); vec4 normals[6] = vec4[](
vec4(-1,0,0,0),
vec4(1,0,0,0),
vec4(0,-1,0,0),
vec4(0,1,0,0),
vec4(0,0,-1,0),
vec4(0,0,1,0)
);
f_norm = f_norm =
// inst_pos * // inst_pos *
normalize(((normals[(v_norm_ao >> 0) & 0x7u]) * attr.rot).xyz); normalize(((normals[(v_norm_ao >> 0) & 0x7u]) * attr.rot).xyz);

View File

@ -26,7 +26,8 @@ impl Animation for GlidingAnimation {
) -> Self::Skeleton { ) -> Self::Skeleton {
let mut next = (*skeleton).clone(); let mut next = (*skeleton).clone();
next.glider_trails = true; // TODO: remove glider trails completely
next.glider_trails = false;
let speednorm = velocity.magnitude().min(50.0) / 50.0; let speednorm = velocity.magnitude().min(50.0) / 50.0;
let slow = (acc_vel * 0.1).sin(); let slow = (acc_vel * 0.1).sin();

View File

@ -1326,26 +1326,53 @@ impl ParticleMgr {
elevation: _, elevation: _,
}) = physics.in_fluid }) = physics.in_fluid
{ {
self.particles.resize_with( // Empirical observation is that air_vel is somewhere
self.particles.len() // between 0.0 and 13.0, but we are extending to be sure
+ usize::from(self.scheduler.heartbeats(Duration::from_millis(10))), // scale with wind speed const MAX_AIR_VEL: f32 = 15.0;
|| { const MIN_AIR_VEL: f32 = -2.0;
let start_pos = interpolated.pos
+ Vec3::new( let minmax_norm = |val, min, max| (val - min) / (max - min);
body.max_radius(),
body.max_radius(), let wind_speed = air_vel.0.magnitude();
body.height() / 2.0,
) // Less means more frequent particles
.map(|d| d * rng.gen_range(-10.0..10.0)); let heartbeat = 200
Particle::new_directed( - Lerp::lerp(
Duration::from_millis(300), // scale with wind speed 50u64,
time, 150,
ParticleMode::Airflow, minmax_norm(wind_speed, MIN_AIR_VEL, MAX_AIR_VEL),
start_pos, );
start_pos + air_vel.0,
) let new_count = self.particles.len()
}, + usize::from(
self.scheduler.heartbeats(Duration::from_millis(heartbeat)),
);
// More number, longer particles
let duration = Lerp::lerp(
0u64,
1000,
minmax_norm(wind_speed, MIN_AIR_VEL, MAX_AIR_VEL),
); );
let duration = Duration::from_millis(duration);
self.particles.resize_with(new_count, || {
let start_pos = interpolated.pos
+ Vec3::new(
body.max_radius(),
body.max_radius(),
body.height() / 2.0,
)
.map(|d| d * rng.gen_range(-10.0..10.0));
Particle::new_directed(
duration,
time,
ParticleMode::Airflow,
start_pos,
start_pos + air_vel.0,
)
});
} }
}, },
_ => {}, _ => {},