update OsgSky

git-svn-id: https://svn.code.sf.net/p/speed-dreams/code/trunk@5332 30fe4595-0a0c-4342-8851-515496e4dcbd

Former-commit-id: de1d7d471bf5b916878d08a92d588cc3df4f58bc
Former-commit-id: ecf02e3200e8689a98b392a26144e92a28b79bf0
This commit is contained in:
torcs-ng 2013-03-18 12:24:37 +00:00
parent b6f8ac69c7
commit d06569ccdf
8 changed files with 193 additions and 134 deletions

View file

@ -200,71 +200,76 @@ inline void sd_clampColor(osg::Vec3& color)
bool SDSkyDome::repaint( const Vec3f& sky_color,
const Vec3f& fog_color, double sun_angle, double vis )
{
osg::Vec3f outer_param, outer_amt, outer_diff;
osg::Vec3f middle_param, middle_amt, middle_diff;
osg::Vec3f outer_param, outer_diff;
osg::Vec3f middle_param, middle_diff;
// Check for sunrise/sunset condition
if (sun_angle > 80)
{
double sunAngleFactor = 10.0 - fabs(90.0 - sun_angle);
static const osg::Vec3f outerConstant(1.0 / 20.0, 1.0 / 40.0, -1.0 / 30.0);
static const osg::Vec3f middleConstant(1.0 / 40.0, 1.0 / 80.0, 0.0);
outer_param = outerConstant * sunAngleFactor;
middle_param = middleConstant * sunAngleFactor;
outer_diff = outer_param * (1.0 / 6.0);
middle_diff = middle_param * (1.0 / 6.0);
} else
{
outer_param = osg::Vec3f(0, 0, 0);
middle_param = osg::Vec3f(0, 0, 0);
outer_diff = osg::Vec3f(0, 0, 0);
middle_diff = osg::Vec3f(0, 0, 0);
}
// Check for sunrise/sunset condition
GfOut("Sun Angle in Dome = %f\n", sun_angle);
outer_amt = outer_param;
middle_amt = middle_param;
if (sun_angle > 80)
{
// 0.0 - 0.4
double sunAngleFactor = 10.0 - fabs(90.0 - sun_angle);
static const osg::Vec3f outerConstant(1.0 / 20.0, 1.0 / 40.0, -1.0 / 30.0);
static const osg::Vec3f middleConstant(1.0 / 40.0, 1.0 / 80.0, 0.0);
outer_param = outerConstant * sunAngleFactor;
middle_param = middleConstant * sunAngleFactor;
outer_diff = outer_param * (1.0 / 6.0);
middle_diff = middle_param * (1.0 / 6.0);
} else
{
outer_param = osg::Vec3f(0, 0, 0);
middle_param = osg::Vec3f(0, 0, 0);
outer_diff = osg::Vec3f(0, 0, 0);
middle_diff = osg::Vec3f(0, 0, 0);
}
/*GfOut(" outer_red_param = %.2f outer_red_diff = %.2f\n",
outer_red_param, outer_red_diff);*/
const double cvf = osg::clampBelow(vis, 45000.0);
const double vis_factor = (vis - 1000.0) / 2000.0; //osg::clampTo((vis - 1000.0) / 2000.0, 0.0, 1.0);
const float upperVisFactor = 1.0 - vis_factor * (0.7 + 0.3 * cvf / 45000);
const float middleVisFactor = 1.0 - vis_factor * (0.1 + 0.85 * cvf / 45000);
osg::Vec3f outer_amt = outer_param;
osg::Vec3f middle_amt = middle_param;
(*dome_cl)[0] = sky_color;
osggraph::SDVectorArrayAdapter<Vec3Array> colors(*dome_cl, numBands, 1);
const double saif = sun_angle / SD_PI;
static const osg::Vec3f blueShift(0.8, 1.0, 1.2);
const osg::Vec3f skyFogDelta = sky_color - fog_color;
// const osg::Vec3f sunSkyDelta = sun_color - sky_color;
const double cvf = osg::clampBelow(vis, 45000.0);
const double vis_factor = osg::clampTo((vis - 1000.0) / 2000.0, 0.0, 1.0);
const float upperVisFactor = 1.0 - vis_factor * (0.7 + 0.3 * cvf/45000);
const float middleVisFactor = 1.0 - vis_factor * (0.1 + 0.85 * cvf/45000);
for (int i = 0; i < halfBands+1; i++)
{
osg::Vec3f diff = componentMultiply(blueShift, skyFogDelta);
diff *= (0.8 + saif - ((halfBands-i)/10));
colors(2, i) = sky_color - diff * upperVisFactor; //toOsg(sky_color - diff * upperVisFactor);
colors(3, i) = sky_color - diff * middleVisFactor + middle_amt; //toOsg(sky_color - diff * middleVisFactor + middle_amt);
colors(4, i) = fog_color + outer_amt; //toOsg(fog_color + outer_amt);
colors(0, i) = sky_color * 0.3942 + colors(2,i) * 0.3942; //lerp(toOsg(sky_color), colors(2, i), .3942);
colors(1, i) = sky_color * 0.7885 + colors(2,i) * 0.7885; //lerp(toOsg(sky_color), colors(2, i), .7885);
for (int j = 0; j < numRings - 1; ++j)
sd_clampColor(colors(j, i));
outer_amt -= outer_diff;
middle_amt -= middle_diff;
}
(*dome_cl)[0] = sky_color;
SDVectorArrayAdapter<Vec3Array> colors(*dome_cl, numBands, 1);
const double saif = sun_angle/SD_PI;
static const osg::Vec3f blueShift(0.8, 1.0, 1.2);
const osg::Vec3f skyFogDelta = sky_color - fog_color;
//const osg::Vec3f sunSkyDelta = sun_color - sky_color;
for (int i = halfBands+1; i < numBands; ++i)
for (int j = 0; j < 5; ++j)
colors(j, i) = colors(j, numBands - i);
for (int i = 0; i < halfBands+1; i++)
{
osg::Vec3f diff = componentMultiply(skyFogDelta, blueShift);
diff *= (0.8 + saif - ((halfBands-i)/10));
colors(2, i) = sky_color - diff * upperVisFactor;
colors(3, i) = sky_color - diff * middleVisFactor + middle_amt;
colors(4, i) = fog_color + outer_amt;
colors(0, i) = sky_color * (1.0 - .3942) + colors(2, i) * .3942;
colors(1, i) = sky_color * (1.0 - 7885) + colors(2, i) * .7885;
for (int j = 0; j < numRings - 1; ++j)
sd_clampColor(colors(j, i));
outer_amt -= outer_diff;
middle_amt -= middle_diff;
}
sd_fade_to_black(&(*dome_cl)[0], asl * center_elev, 1);
for (int i = 0; i < numRings - 1; ++i)
sd_fade_to_black(&colors(i, 0), (asl+0.05f) * domeParams[i].elev,
numBands);
for (int i = halfBands+1; i < numBands; ++i)
for (int j = 0; j < 5; ++j)
colors(j, i) = colors(j, numBands - i);
for ( int i = 0; i < numBands; i++ )
colors(numRings - 1, i) = fog_color;//toOsg(fog_color);
dome_cl->dirty();
sd_fade_to_black(&(*dome_cl)[0], asl * center_elev, 1);
for (int i = 0; i < numRings - 1; ++i)
sd_fade_to_black(&colors(i, 0), (asl+0.05f) * domeParams[i].elev,
numBands);
return true;
for ( int i = 0; i < numBands; i++ )
colors(numRings - 1, i) = fog_color;
dome_cl->dirty();
return true;
}
bool SDSkyDome::reposition( const osg::Vec3f& p, double spin )

View file

@ -62,7 +62,7 @@ static double SDVisibility = 0.0f;
#define MAX_BODIES 2
#define MAX_CLOUDS 3
#define NMaxStars 1000
#define NMaxStars 3000
#define NPLANETS 0 //No planets displayed
#define NB_BG_FACES 36 //Background faces
#define BG_DIST 1.0f
@ -72,10 +72,14 @@ static double SDVisibility = 0.0f;
#define SCARCE_CLOUD 5
#define COVERAGE_CLOUD 8
static const osg::Vec4 BaseSkyColor ( 0.31f, 0.43f, 0.69f, 1.0f );
static osg::Vec3d *AStarsData = NULL;
static osg::Vec3d *APlanetsData = NULL;
static int NStars;
static int NPlanets;
static float sol_angle;
static float moon_angle;
static osg::ref_ptr<osg::Group> RealRoot = new osg::Group;
@ -105,7 +109,7 @@ osg::Node* SDRender::Init(osg::Group *m_sceneroot, tTrack *track)
GfOut("SDSky class\n");
int SDSkyDomeDistance = 12000;
int NStars = NMaxStars;
NStars = NMaxStars;
if (AStarsData)
delete [] AStarsData;
@ -120,7 +124,7 @@ osg::Node* SDRender::Init(osg::Group *m_sceneroot, tTrack *track)
GfLogInfo(" Stars (random) : %d\n", NStars);
int NPlanets = 0;
NPlanets = 0;
APlanetsData = NULL;
GfLogInfo(" Planets : %d\n", NPlanets);
@ -172,7 +176,8 @@ osg::Node* SDRender::Init(osg::Group *m_sceneroot, tTrack *track)
thesky->reposition( viewPos, 0, 0);
UpdateLight();
//thesky->repaint()
thesky->repaint(SkyColor, FogColor, CloudsColor, sol_angle, moon_angle, NPlanets,
APlanetsData, NStars, AStarsData);
osg::Group* sceneGroup = new osg::Group;
sceneGroup->addChild(m_sceneroot);
@ -215,8 +220,8 @@ osg::Node* SDRender::Init(osg::Group *m_sceneroot, tTrack *track)
void SDRender::UpdateLight( void )
{
const float sol_angle = (float)thesky->getSA();
const float moon_angle = (float)thesky->getMA();
sol_angle = (float)thesky->getSA();
moon_angle = (float)thesky->getMA();
float sky_brightness = (float)(1.0 + cos(sol_angle)) / 2.0f;
GfOut("Sun Angle in Render = %f\n", sol_angle);

View file

@ -24,6 +24,19 @@
#include <osg/StateSet>
#include <osg/Depth>
// Used for rise/set effects (flat earth - no rotation of skydome considered here )
void calc_celestial_angles( const osg::Vec3f& body, const osg::Vec3f& view, double& angle, double& rotation )
{
osg::Vec3f pos = body - view;
/*pos.x() = body.x() - view.x();
pos.y() = body.y() - view.y();
pos.z() = body.z() - view.z();*/
//sgSubVec3(pos, body, view);
angle = (90*SD_DEGREES_TO_RADIANS) - atan2(pos[2], sqrt(pos[0]*pos[0] + pos[1]*pos[1]));
rotation = (90*SD_DEGREES_TO_RADIANS) - atan2(pos[0], pos[1]);
}
// Constructor
SDSky::SDSky( void )
{
@ -105,7 +118,7 @@ bool SDSky::repaint( osg::Vec3f& sky_color, osg::Vec3f& fog_color, osg::Vec3f& c
{
if ( effective_visibility > 1000.0 )
{
enable();
enable();
dome->repaint( sky_color, fog_color, sol_angle, effective_visibility );
sun->repaint( sol_angle, effective_visibility );
@ -120,7 +133,7 @@ bool SDSky::repaint( osg::Vec3f& sky_color, osg::Vec3f& fog_color, osg::Vec3f& c
}*/
planets->repaint( sol_angle, nplanets, planet_data );
stars->repaint( sol_angle, nstars, star_data);
stars->repaint( sol_angle, nstars, star_data );
} else
{
// turn off sky
@ -134,9 +147,18 @@ bool SDSky::repaint( osg::Vec3f& sky_color, osg::Vec3f& fog_color, osg::Vec3f& c
bool SDSky::reposition( osg::Vec3& view_pos, double spin, /*double gst,*/
double dt )
{
sun->reposition( view_pos );
double angle;
double rotation;
sun->reposition( view_pos, 0 );
moon->reposition( view_pos, 0 );
dome->reposition( view_pos, 0 );
osg::Vec3f sunpos = sun->getSunPosition ();
calc_celestial_angles( sunpos, view_pos, angle, rotation );
sun->setSunAngle( angle );
sun->setSunRotation( rotation );
dome->reposition( view_pos, angle );
//sun->getSunPosition ( & pos );
//calc_celestial_angles( pos, view_pos, angle, rotation );

View file

@ -37,8 +37,7 @@
#include "OsgMath.h"
// Constructor
SDStars::SDStars( void ) :
old_phase(-1)
SDStars::SDStars( void ) : old_phase(-1)
{
}
@ -65,7 +64,7 @@ osg::Node* SDStars::build( int num, const osg::Vec3d star_data[], double star_di
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
cl = new osg::Vec4Array;
stars_cl = new osg::Vec4Array;
osg::Vec3Array* vl = new osg::Vec3Array;
for ( int i = 0; i < num; ++i )
@ -75,13 +74,13 @@ osg::Node* SDStars::build( int num, const osg::Vec3d star_data[], double star_di
star_dist * sin( star_data[i][0])
* cos( star_data[i][1] ),
star_dist * sin( star_data[i][1])));
cl->push_back(osg::Vec4(1, 1, 1, 1));
stars_cl->push_back(osg::Vec4(1, 1, 1, 1));
}
osg::Geometry* geometry = new osg::Geometry;
geometry->setUseDisplayList(false);
geometry->setVertexArray(vl);
geometry->setColorArray(cl.get());
geometry->setColorArray(stars_cl.get());
geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
geometry->setNormalBinding(osg::Geometry::BIND_OFF);
geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vl->size()));
@ -90,6 +89,18 @@ osg::Node* SDStars::build( int num, const osg::Vec3d star_data[], double star_di
return geode;
}
/*bool cGrStars::reposition( osg::Vec3f& p, double angle )
{
osg::Matrix T, SPIN;
T.makeTranslate( p );
SPIN.makeRotate(spin, osg::Vec3(0, 0, 1));
star_transform->setMatrix( SPIN*T );
return true;
}*/
bool SDStars::repaint( double sun_angle, int num, const osg::Vec3d star_data[] )
{
double mag, nmag, alpha, factor, cutoff;
@ -102,44 +113,54 @@ bool SDStars::repaint( double sun_angle, int num, const osg::Vec3d star_data[] )
factor = 1.0;
cutoff = 4.5;
phase = 0;
//GfOut("Stars = %f\n", 10.0f);
} else if ( sun_angle > (SD_PI_2 + 8.8 * SD_DEGREES_TO_RADIANS ) )
{
factor = 1.0;
cutoff = 3.8;
phase = 1;
//GfOut("Stars = %f\n", 8.0f);
} else if ( sun_angle > (SD_PI_2 + 7.5 * SD_DEGREES_TO_RADIANS ) )
{
factor = 0.95;
cutoff = 3.1;
phase = 2;
//GfOut("Stars = %f\n", 7.5f);
} else if ( sun_angle > (SD_PI_2 + 7.0 * SD_DEGREES_TO_RADIANS ) )
{
factor = 0.9;
cutoff = 2.4;
phase = 3;
//GfOut("Stars = %f\n", 7.0f);
} else if ( sun_angle > (SD_PI_2 + 6.5 * SD_DEGREES_TO_RADIANS ) )
{
factor = 0.85;
cutoff = 1.8;
phase = 4;
//GfOut("Stars = %f\n", 6.5f);
} else if ( sun_angle > (SD_PI_2 + 6.0 * SD_DEGREES_TO_RADIANS ) )
{
factor = 0.8;
cutoff = 1.2;
phase = 5;
//GfOut("Stars = %f\n", 6.0f);
} else if ( sun_angle > (SD_PI_2 + 5.5 * SD_DEGREES_TO_RADIANS ) )
{
factor = 0.75;
cutoff = 0.6;
phase = 6;
//GfOut("Stars = %f\n", 5.5f);
} else
{
factor = 0.7;
cutoff = 0.0;
phase = 7;
//GfOut("Stars default\n");
}
if( phase != old_phase )
GfOut("Phase = %d - old_phase = %d\n", phase, old_phase);
if ( phase != old_phase )
{
old_phase = phase;
for ( int i = 0; i < num; ++i )
@ -150,20 +171,24 @@ bool SDStars::repaint( double sun_angle, int num, const osg::Vec3d star_data[] )
nmag = ( 4.5 - mag ) / 5.5;
alpha = nmag * 0.85 + 0.15;
alpha *= factor;
} else
//GfOut("Alpha = %f\n", alpha);
}
else
{
alpha = 0.0;
//GfOut("Stars desactivée\n");
}
if (alpha > 1.0) { alpha = 1.0; }
if (alpha < 0.0) { alpha = 0.0; }
(*cl)[i] = osg::Vec4(1, 1, 1, alpha);
(*stars_cl)[i] = osg::Vec4f(1.0f, 1.0f, 1.0f, (float)alpha);
}
cl->dirty();
} else
stars_cl->dirty();
}
else
{
// cout << " no phase change, skipping" << endl;
//GfOut(" no phase change, skipping\n");
}
return true;

View file

@ -24,7 +24,7 @@
class SDStars
{
osg::ref_ptr<osg::Vec4Array> cl;
osg::ref_ptr<osg::Vec4Array> stars_cl;
int old_phase;
public:

View file

@ -215,14 +215,14 @@ bool SDSun::repaint( double sun_angle, double new_visibility )
osg::Vec4 i_halo_color, o_halo_color, scene_color, sun_color;
double red_scat_f, red_scat_corr_f, green_scat_f, blue_scat_f;
double red_scat_f, /*red_scat_corr_f,*/ green_scat_f, blue_scat_f;
red_scat_f = (aerosol_factor * path_distance * density_avg) / 5E+07;
red_scat_corr_f = sun_exp2_punch_through / (1 - red_scat_f);
//red_scat_corr_f = sun_exp2_punch_through / (1 - red_scat_f);
sun_color[0] = 1 -red_scat_f;
i_halo_color[0] = 1 - (1.1 * red_scat_f);
o_halo_color[0] = 1 - (1.4 * red_scat_f);
scene_color[0] = 1 - red_scat_f;
//scene_color[0] = 1 - red_scat_f;
// Green - 546.1 nm
if (sun_declination > 5.0 || sun_declination < 2.0)
@ -338,21 +338,23 @@ bool SDSun::repaint( double sun_angle, double new_visibility )
return true;
}
bool SDSun::reposition( osg::Vec3d p/*, double angle*/)
bool SDSun::reposition( osg::Vec3d p, double angle)
{
osg::Matrix T1, RA, DEC;
osg::Matrix T1, RA, DEC, T2, GST;
T1.makeTranslate(p);
GST.makeRotate((float)(angle), osg::Vec3(0.0, 0.0, -1.0));
RA.makeRotate((float)(sun_right_ascension - 90 *SD_DEGREES_TO_RADIANS) , osg::Vec3(0, 0, 1));
DEC.makeRotate((float)(sun_declination), osg::Vec3(1, 0, 0));
T1.makeTranslate(0, sun_dist, 0);
T2.makeTranslate(0, sun_dist, 0);
osg::Matrix R = T1*DEC*RA;
osg::Matrix R = T2*T1*GST*DEC*RA;
sun_transform->setMatrix(R);
osg::Vec4f pos = osg::Vec4f(0.0,0.0,0.0,1.0)*R;
sun_position = osg::Vec3f(pos._v[0],pos._v[1],pos._v[2]);
GfOut("Sun Position : %f %f %f %f %f\n", pos._v[0], pos._v[1], pos._v[2],sun_dist,pos.length());
GfOut("Sun Position in Sun: %f %f %f %f %f\n", pos._v[0], pos._v[1], pos._v[2],sun_dist,pos.length());
osg::Vec3f upos = osg::Vec3f(sun_position);
osg::Vec3f uplan = osg::Vec3f(sun_position._v[0],0.0,sun_position._v[2]);
@ -360,7 +362,7 @@ bool SDSun::reposition( osg::Vec3d p/*, double angle*/)
uplan.normalize();
sun_angle_to_scene = acos(upos*uplan);
sun_angle = sun_angle_to_scene;
//sun_angle = sun_angle_to_scene;
GfOut("Sun Angle = %f\n", sun_angle);

View file

@ -58,7 +58,7 @@ public:
osg::Node* build( std::string path, double dist, double sun_size );
bool repaint( double sun_angle, double new_visibility );
bool reposition( osg::Vec3d p);
bool reposition( osg::Vec3d p, double angle);
osg::Vec4f get_color();
osg::Vec4f get_scene_color();

View file

@ -62,10 +62,10 @@ cGrSky::~cGrSky( void )
void cGrSky::build( double h_radius, double v_radius,
double sun_size, double sun_dist,
double sun_size, double sun_dist,
double moon_size, double moon_dist,
int nplanets, sgdVec3 *planet_data,
int nstars, sgdVec3 *star_data )
int nstars, sgdVec3 *star_data )
{
delete dome;
delete sun;
@ -148,23 +148,23 @@ bool cGrSky::repositionFlat( sgVec3 view_pos, double spin, double dt )
double angle;
double rotation;
sgCoord pos;
// Calc angles for rise/set effects
sun->reposition( view_pos, 0 );
moon->reposition( view_pos, 0 );
sun->getSunPosition ( & pos );
calc_celestial_angles( pos.xyz, view_pos, angle, rotation );
calc_celestial_angles( pos.xyz, view_pos, angle, rotation );
sun->setSunAngle( angle );
sun->setSunRotation( rotation );
moon->getMoonPosition ( & pos );
calc_celestial_angles( pos.xyz, view_pos, angle, rotation );
moon->getMoonPosition ( & pos );
calc_celestial_angles( pos.xyz, view_pos, angle, rotation );
moon->setMoonAngle( angle );
moon->setMoonRotation( rotation );
for ( i = 0; i < clouds.getNum (); i++ )
for ( i = 0; i < clouds.getNum (); i++ )
{
clouds.get(i)->repositionFlat( view_pos, dt );
}
@ -203,7 +203,7 @@ bool cGrSky::repaint( sgVec4 sky_color, sgVec4 fog_color, sgVec4 cloud_color, do
{
int i;
if ( effective_visibility > 300.0 )
if ( effective_visibility > 300.0 )
{
// turn on sky
enable();
@ -221,7 +221,7 @@ bool cGrSky::repaint( sgVec4 sky_color, sgVec4 fog_color, sgVec4 cloud_color, do
stars->repaint( sol_angle, nstars, star_data );
}
else
else
{
// turn off sky
disable();
@ -242,11 +242,11 @@ void cGrSky::postDraw( float alt )
// Sort clouds in order of distance from alt (furthest to closest)
int i, j;
int num = clouds.getNum ();
if ( num > 0 )
if ( num > 0 )
{
// Initialise cloud index
int *index = new int [ num ];
for ( i = 0; i < num; i++ )
for ( i = 0; i < num; i++ )
{
index [i] = i;
}
@ -271,7 +271,7 @@ void cGrSky::postDraw( float alt )
float slop = 5.0; // if we are closer than this to a cloud layer, don't draw cloud
for ( int i = 0; i < num; i++ )
for ( int i = 0; i < num; i++ )
{
cGrCloudLayer *cloud = clouds.get(index[i]);
@ -291,11 +291,11 @@ void cGrSky::modifyVisibility( float alt, float time_factor )
{
float effvis = visibility;
for ( int i = 0; i < clouds.getNum (); ++i )
for ( int i = 0; i < clouds.getNum (); ++i )
{
cGrCloudLayer *cloud = clouds.get(i);
if ( cloud->isEnabled() )
if ( cloud->isEnabled() )
{
float asl = cloud->getElevation();
float thickness = cloud->getThickness();
@ -303,27 +303,27 @@ void cGrSky::modifyVisibility( float alt, float time_factor )
float ratio = 1.0;
if ( alt < asl - transition )
if ( alt < asl - transition )
{
// below cloud layer
ratio = 1.0;
}
else if ( alt < asl )
else if ( alt < asl )
{
// in lower transition
ratio = (asl - alt) / transition;
}
else if ( alt < asl + thickness )
else if ( alt < asl + thickness )
{
// in cloud layer
ratio = 0.0;
}
else if ( alt < asl + thickness + transition )
else if ( alt < asl + thickness + transition )
{
// in upper transition
ratio = (alt - (asl + thickness)) / transition;
}
else
else
{
// above cloud layer
ratio = 1.0;
@ -332,56 +332,56 @@ void cGrSky::modifyVisibility( float alt, float time_factor )
// accumulate effects from multiple cloud layers
effvis *= ratio;
if ( ratio < 1.0 )
if ( ratio < 1.0 )
{
if ( ! in_puff )
{
if ( ! in_puff )
{
// calc chance of entering cloud puff
double rnd = grRandom();
double chance = rnd * rnd * rnd;
if ( chance > 0.95 )
{
if ( chance > 0.95 )
{
in_puff = true;
puff_length = grRandom() * 2.0; // up to 2 seconds
puff_progression = 0.0;
}
}
}
}
if ( in_puff )
if ( in_puff )
{
// modify actual_visibility based on puff envelope
if ( puff_progression <= ramp_up )
// modify actual_visibility based on puff envelope
if ( puff_progression <= ramp_up )
{
double x = 0.5 * SGD_PI * puff_progression / ramp_up;
double factor = 1.0 - sin( x );
effvis = (float)(effvis * factor);
double x = 0.5 * SGD_PI * puff_progression / ramp_up;
double factor = 1.0 - sin( x );
effvis = (float)(effvis * factor);
}
else if ( puff_progression >= ramp_up + puff_length )
{
double x = 0.5 * SGD_PI *
(puff_progression - (ramp_up + puff_length)) /
ramp_down;
double factor = sin( x );
effvis = (float)(effvis * factor);
else if ( puff_progression >= ramp_up + puff_length )
{
double x = 0.5 * SGD_PI *
(puff_progression - (ramp_up + puff_length)) /
ramp_down;
double factor = sin( x );
effvis = (float)(effvis * factor);
}
else
else
{
effvis = 0.0;
}
}
puff_progression += time_factor;
if ( puff_progression > puff_length + ramp_up + ramp_down)
if ( puff_progression > puff_length + ramp_up + ramp_down)
{
in_puff = false;
in_puff = false;
}
}
// never let visibility drop below 25 meters
if ( effvis <= 25.0 )
{
if ( effvis <= 25.0 )
{
effvis = 25.0;
}
}
}
}
} // for