mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-21 16:33:00 +02:00
Let the templates of smoke sources set how fast their particles rise or fall
This commit is contained in:
@@ -269,6 +269,11 @@ are no longer loaded.
|
||||
what it doesn't see and lights the rest with the sun (with the shadows of the terrain, models and clouds), the sky and
|
||||
the lamps and headlights, as the surfaces are lit: smoke in the shade is darker, smoke against the sun glows, smoke in
|
||||
the beam of headlights at night is lit by it.
|
||||
- **Templates of smoke sources** (`data/smokesource_*.txt`, both renderers) may say how heavy the particles are: with
|
||||
`terminal_velocity: v` (m/s, positive up: light, hot smoke rises; negative down: dust, sand, sparks fall) the velocity
|
||||
of a particle goes over to `v` (straight up or down, besides the drift with the wind), the faster the larger `drag: d`
|
||||
(per second, default 1: about 63% of the way in a second). It takes the place of the old rules of the rise (slower in
|
||||
cold and humid air); a template without it behaves as before. The particles don't stop at the ground.
|
||||
- **Rain and snow** are particles in three boxes around the camera (10, 24 and 60 metres), more of them the heavier the
|
||||
rain or snow (the overcast above 1). The drops and flakes fall, drift with the wind, the flakes flutter, and each is
|
||||
drawn as a streak of its motion against the camera: they slant when the train moves. They are lit like the smoke, so the
|
||||
|
||||
3
gl/ubo.h
3
gl/ubo.h
@@ -526,10 +526,11 @@ namespace gl
|
||||
glm::vec4 sizechange;
|
||||
glm::vec4 opacitychange;
|
||||
glm::vec4 motion;
|
||||
glm::vec4 settling;
|
||||
glm::vec4 color;
|
||||
glm::vec4 oldcolor;
|
||||
};
|
||||
static_assert(sizeof(particle_smoke_source) == 160, "bad size of particle_smoke_source");
|
||||
static_assert(sizeof(particle_smoke_source) == 176, "bad size of particle_smoke_source");
|
||||
|
||||
// layout std430: GLSL particle_draw_s, read by the draws as attributes of instances
|
||||
struct particle_draw
|
||||
|
||||
@@ -249,6 +249,7 @@ void opengl46_gpu_particles::simulate_smoke(particle_manager &Particles, glm::dv
|
||||
record.sizechange = glm::vec4{state.sizechange[0], state.sizechange[1], state.sizechange[2], 0.f};
|
||||
record.opacitychange = glm::vec4{state.opacitychange[0], state.opacitychange[1], state.opacitychange[2], 0.f};
|
||||
record.motion = glm::vec4{state.rise, state.damping, state.risemin, 0.f};
|
||||
record.settling = glm::vec4{state.settling, state.drag, state.settles ? 1.f : 0.f, 0.f};
|
||||
record.color = glm::vec4{glm::clamp(state.color, glm::vec3{0.f}, glm::vec3{1.f}), 0.f};
|
||||
record.oldcolor = glm::vec4{glm::clamp(state.color * oldlight, glm::vec3{0.f}, glm::vec3{1.f}), 0.f};
|
||||
if (pool.size > 0)
|
||||
|
||||
@@ -115,6 +115,13 @@ smoke_source::deserialize_mapping( cParser &Input ) {
|
||||
else if( key == "opacity_change:" ) {
|
||||
m_opacitymodifier.deserialize( Input );
|
||||
}
|
||||
else if( key == "terminal_velocity:" ) {
|
||||
m_settles = true;
|
||||
m_settling = Input.getToken<float>( true, "\n\r\t ,;[]" );
|
||||
}
|
||||
else if( key == "drag:" ) {
|
||||
m_drag = std::max( 0.f, Input.getToken<float>( true, "\n\r\t ,;[]" ) );
|
||||
}
|
||||
|
||||
return true; // return value marks a [ key: value ] pair was extracted, nothing about whether it's recognized
|
||||
}
|
||||
@@ -379,9 +386,14 @@ smoke_source::update( smoke_particle &Particle, bounding_box &Boundingbox, doubl
|
||||
// ... otherwise proceed with full update
|
||||
m_sizemodifier.update( Particle.size, Timedelta );
|
||||
|
||||
if( m_settles ) {
|
||||
// the drag of the air takes the particle towards the velocity it settles at
|
||||
auto const share { static_cast<float>( 1.0 - std::exp( -m_drag * Timedelta ) ) };
|
||||
Particle.velocity += ( glm::vec3{ 0.f, m_settling, 0.f } - Particle.velocity ) * share;
|
||||
}
|
||||
// crude smoke dispersion simulation
|
||||
// http://www.auburn.edu/academic/forestry_wildlife/fire/smoke_guide/smoke_dispersion.htm
|
||||
if (m_ownertype == owner_type::vehicle)
|
||||
else if (m_ownertype == owner_type::vehicle)
|
||||
{
|
||||
Particle.velocity.y += static_cast<float>(( 0.025 * Particle.velocity.y ) * std::min( 0.f, Global.AirTemperature - 90 ) * Timedelta); // decelerate faster in cold weather
|
||||
Particle.velocity.y -= static_cast<float>(( (0.05 * (pow(m_owner.vehicle->GetVelocity()*1,0.4))) * Particle.velocity.y ) * Global.Overcast * Timedelta); // decelerate faster with high air humidity and/or precipitation
|
||||
@@ -451,6 +463,9 @@ smoke_source::update_gpu( double const Timedelta, bool const Onlydespawn ) {
|
||||
m_gpu.damping = static_cast<float>( 0.050 * Global.Overcast );
|
||||
m_gpu.risemin = static_cast<float>( 0.25 * ( 2.f - Global.Overcast ) );
|
||||
}
|
||||
m_gpu.settles = m_settles;
|
||||
m_gpu.settling = m_settling;
|
||||
m_gpu.drag = m_drag;
|
||||
m_gpu.color = m_emitter.color;
|
||||
|
||||
// the renderer culls the particles one by one; the area is where they come from, for the distance of the source
|
||||
|
||||
@@ -101,6 +101,10 @@ public:
|
||||
float rise { 0.f };
|
||||
float damping { 0.f };
|
||||
float risemin { std::numeric_limits<float>::lowest() };
|
||||
// with a settling velocity (settles): the velocity goes over to it instead, see smoke_source::m_settling
|
||||
bool settles { false };
|
||||
float settling { 0.f };
|
||||
float drag { 1.f };
|
||||
glm::vec3 color { 0.f };
|
||||
};
|
||||
// methods
|
||||
@@ -189,6 +193,12 @@ private:
|
||||
fixedstep_modifier<float> m_sizemodifier; // particle billboard size
|
||||
// fixedstep_modifier<glm::vec3> m_colormodifier; // particle billboard color and opacity
|
||||
fixedstep_modifier<float> m_opacitymodifier;
|
||||
// optional velocity the particles settle at in still air, m/s, positive upwards (light, hot smoke rises, heavy particles
|
||||
// fall), and how fast they get to it: the share of the rest of the way per second is 1 - exp(-drag). when given, it takes
|
||||
// the place of the crude dispersion of update( Particle ) (the rise in cold air, the damping in humid air)
|
||||
bool m_settles { false };
|
||||
float m_settling { 0.f }; // terminal_velocity:
|
||||
float m_drag { 1.f }; // drag:
|
||||
// texture_handle m_texture { -1 }; // texture assigned to particle billboards
|
||||
// current state
|
||||
float m_spawncount { 0.f }; // number of particles to spawn during next update
|
||||
|
||||
@@ -22,6 +22,7 @@ struct smoke_source_s
|
||||
vec4 sizechange; // x: per second, y: min, z: max
|
||||
vec4 opacitychange; // x: per second, y: min, z: max
|
||||
vec4 motion; // x: rise, y: damping (per second, of the vertical velocity), z: least vertical velocity
|
||||
vec4 settling; // x: velocity the particles settle at, m/s upwards, y: drag, per second, z: 1 when they settle (in place of motion)
|
||||
vec4 color; // rgb: colour of the smoke, lit by the lights of the pass
|
||||
vec4 oldcolor; // rgb: colour lit as the cpu does it, without the lights (gfx.smoke.lighting off)
|
||||
};
|
||||
|
||||
@@ -37,10 +37,18 @@ bool advance(inout smoke_particle_s particle, smoke_source_s source, float secon
|
||||
if (particle.state.x <= 0.0)
|
||||
return false;
|
||||
particle.velocity.w = clamp(particle.velocity.w + source.sizechange.x * seconds, source.sizechange.y, source.sizechange.z);
|
||||
// crude smoke dispersion
|
||||
particle.velocity.y += source.motion.x * particle.velocity.y * seconds;
|
||||
particle.velocity.y -= source.motion.y * particle.velocity.y * seconds;
|
||||
particle.velocity.y = max(source.motion.z, particle.velocity.y);
|
||||
if (source.settling.z > 0.5)
|
||||
{
|
||||
// the drag of the air takes the particle towards the velocity it settles at
|
||||
particle.velocity.xyz += (vec3(0.0, source.settling.x, 0.0) - particle.velocity.xyz) * (1.0 - exp(-source.settling.y * seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
// crude smoke dispersion
|
||||
particle.velocity.y += source.motion.x * particle.velocity.y * seconds;
|
||||
particle.velocity.y -= source.motion.y * particle.velocity.y * seconds;
|
||||
particle.velocity.y = max(source.motion.z, particle.velocity.y);
|
||||
}
|
||||
particle.position.xyz += particle.velocity.xyz * seconds;
|
||||
particle.position.xyz += 0.1 * particle.state.y * wind.xyz * seconds;
|
||||
particle.state.y += seconds;
|
||||
|
||||
Reference in New Issue
Block a user