scenery model smoke source binding, smoke dispersion tweaks, wind simulation tweak

This commit is contained in:
tmj-fstate
2019-08-08 00:48:11 +02:00
parent 69130d54a0
commit c951b1b955
4 changed files with 46 additions and 53 deletions

View File

@@ -117,11 +117,6 @@ smoke_source::initialize() {
// this gives us estimate of longest potential lifespan of single particle, and how many particles total can there be at any given time
// TBD, TODO: explicit lifespan variable as part of the source configuration?
static_cast<int>( m_spawnrate / std::abs( m_opacitymodifier.value_change() ) ) ) );
/*
m_particlehead =
m_particletail =
std::begin( m_particles );
*/
}
void
@@ -134,6 +129,16 @@ smoke_source::bind( TDynamicObject const *Vehicle ) {
owner_type::none );
}
void
smoke_source::bind( TAnimModel const *Node ) {
m_owner.node = Node;
m_ownertype = (
m_owner.node != nullptr ?
owner_type::node :
owner_type::none );
}
// updates state of owned particles
void
smoke_source::update( double const Timedelta, bool const Onlydespawn ) {
@@ -151,32 +156,6 @@ smoke_source::update( double const Timedelta, bool const Onlydespawn ) {
m_spawncount + ( m_spawnrate * Timedelta ),
m_particles.capacity() ) );
// update spawned particles
/*
while( m_particlehead != m_particletail ) {
auto &particle { *m_particlehead };
bool particleisalive;
while( ( false == ( particleisalive = update( particle, Timedelta ) ) )
&& ( m_spawncount >= 1.f ) ) {
// replace dead particle with a new one
m_spawncount -= 1.f;
initialize( particle );
}
if( false == particleisalive ) {
// we have a dead particle and no pending spawn requests, (try to) move the last particle here
do {
--m_particletail;
if( m_particlehead == m_particletail ) { break; }
particle = *m_particletail;
} while( false == ( particleisalive = update( particle, Timedelta ) ) );
}
if( true == particleisalive ) {
// ensure at the end of the pass the head iterator is placed after the last alive particle
++m_particlehead;
}
}
*/
for( auto particleiterator { std::begin( m_particles ) }; particleiterator != std::end( m_particles ); ++particleiterator ) {
auto &particle { *particleiterator };
@@ -205,18 +184,6 @@ smoke_source::update( double const Timedelta, bool const Onlydespawn ) {
}
}
// spawn pending particles in remaining container slots
/*
while( ( m_spawncount >= 1.f )
&& ( m_particlehead != std::end( m_particles ) ) ) {
m_spawncount -= 1.f;
auto &particle { *m_particlehead };
initialize( particle );
if( true == update( particle, Timedelta ) ) {
++m_particlehead;
}
}
*/
while( ( m_spawncount >= 1.f )
&& ( m_particles.size() < m_particles.capacity() ) ) {
@@ -258,12 +225,6 @@ smoke_source::update( double const Timedelta, bool const Onlydespawn ) {
// discard pending spawn requests our container couldn't fit
m_spawncount -= std::floor( m_spawncount );
}
/*
// after the pass the head iterator is left last alive particle
m_particletail = m_particlehead;
m_particlehead = std::begin( m_particles );
*/
// determine bounding area from calculated bounding box
if( false == m_particles.empty() ) {
m_area.center = interpolate( boundingbox[ value_limit::min ], boundingbox[ value_limit::max ], 0.5 );
@@ -291,7 +252,8 @@ smoke_source::location() const {
}
case owner_type::node: {
// TODO: take into account node rotation
location = m_offset;
auto const rotation { glm::angleAxis( glm::radians( m_owner.node->Angles().y ), glm::vec3{ 0.f, 1.f, 0.f } ) };
location = rotation * glm::vec3{ m_offset };
location += m_owner.node->location();
break;
}
@@ -342,10 +304,12 @@ smoke_source::update( smoke_particle &Particle, bounding_box &Boundingbox, doubl
// crude smoke dispersion simulation
// http://www.auburn.edu/academic/forestry_wildlife/fire/smoke_guide/smoke_dispersion.htm
Particle.velocity.y = std::max<float>( 0.25 * ( 1.f - Global.Overcast ), Particle.velocity.y - 0.25 * Global.Overcast * Timedelta );
Particle.velocity.y += ( 0.005 * Particle.velocity.y ) * std::min( 0.f, Global.AirTemperature - 10 ) * Timedelta; // decelerate faster in cold weather
Particle.velocity.y -= ( 0.010 * Particle.velocity.y ) * Global.Overcast * Timedelta; // decelerate faster with high air humidity and/or precipitation
Particle.velocity.y = std::max<float>( 0.25 * ( 2.f - Global.Overcast ), Particle.velocity.y ); // put a cap on deceleration
Particle.position += Particle.velocity * static_cast<float>( Timedelta );
Particle.position += 0.35f * simulation::Environment.wind() * static_cast<float>( Timedelta );
Particle.position += 0.1f * Particle.age * simulation::Environment.wind() * static_cast<float>( Timedelta );
// m_velocitymodifier.update( Particle.velocity, Timedelta );
Particle.age += Timedelta;
@@ -389,6 +353,18 @@ particle_manager::insert( std::string const &Sourcetemplate, TDynamicObject cons
return true;
}
bool
particle_manager::insert( std::string const &Sourcetemplate, TAnimModel const *Node, glm::dvec3 const Location ) {
if( false == insert( Sourcetemplate, Location ) ) { return false; }
// attach the source to specified node
auto &source { m_sources.back() };
source.bind( Node );
return true;
}
// updates state of all owned emitters
void
particle_manager::update() {

View File

@@ -81,6 +81,8 @@ public:
initialize();
void
bind( TDynamicObject const *Vehicle );
void
bind( TAnimModel const *Node );
// updates state of owned particles
void
update( double const Timedelta, bool const Onlydespawn );
@@ -171,6 +173,8 @@ public:
insert( std::string const &Sourcetemplate, glm::dvec3 const Location );
bool
insert( std::string const &Sourcetemplate, TDynamicObject const *Vehicle, glm::dvec3 const Location );
bool
insert( std::string const &Sourcetemplate, TAnimModel const *Node, glm::dvec3 const Location );
// updates state of all owned emitters
void
update();

View File

@@ -195,8 +195,12 @@ world_environment::update_wind() {
m_wind.change_time -= timedelta;
if( m_wind.change_time < 0 ) {
m_wind.change_time = Random( 5, 30 );
m_wind.azimuth_change = Random( -5, 5 );
m_wind.velocity_change = Random( -1, 1 );
if( Random() < 0.2 ) {
// changes in wind direction should be less frequent than changes in wind speed
// TBD, TODO: configuration-driven direction change frequency
m_wind.azimuth_change = Random( -5, 5 );
}
}
// TBD, TODO: wind configuration
m_wind.azimuth = clamp_circular( m_wind.azimuth + m_wind.azimuth_change * timedelta );

View File

@@ -458,6 +458,15 @@ state_serializer::deserialize_node( cParser &Input, scene::scratch_data &Scratch
// model import can potentially fail
if( instance == nullptr ) { return; }
if( instance->Model() != nullptr ) {
for( auto const &smokesource : instance->Model()->smoke_sources() ) {
Particles.insert(
smokesource.first,
instance,
smokesource.second );
}
}
if( false == simulation::Instances.insert( instance ) ) {
ErrorLog( "Bad scenario: duplicate 3d model instance name \"" + instance->name() + "\" defined in file \"" + Input.Name() + "\" (line " + std::to_string( inputline ) + ")" );
}