]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/sky/oursun.cxx
Merge branch 'ehofman/sound'
[simgear.git] / simgear / scene / sky / oursun.cxx
index dd0d2cad986c1ed208c90cb893d1acc67d2d7b3c..db7e73198cb69c8cf47c7ed0d738fed41cdfe8f4 100644 (file)
 #include <osg/Texture2D>
 #include <osgDB/ReadFile>
 
+#include <simgear/math/SGMath.hxx>
+#include <simgear/misc/PathOptions.hxx>
 #include <simgear/screen/colors.hxx>
 #include <simgear/scene/model/model.hxx>
 #include "oursun.hxx"
 
+using namespace simgear;
+
 // Constructor
-SGSun::SGSun( void ) {
-    prev_sun_angle = -9999.0;
-    visibility = -9999.0;
+SGSun::SGSun( void ) :
+    visibility(-9999.0), prev_sun_angle(-9999.0), path_distance(60000.0),
+    sun_exp2_punch_through(7.0e-06)
+{
+
 }
 
 
@@ -63,8 +69,8 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
 
     env_node = property_tree_Node;
 
-    SGPath ihalopath = path, ohalopath = path;
-
+    osg::ref_ptr<osgDB::ReaderWriter::Options> options
+        = makeOptionsFromPath(path);
     // build the ssg scene graph sub tree for the sky and connected
     // into the provide scene graph branch
     sun_transform = new osg::MatrixTransform;
@@ -76,19 +82,16 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
  
     osg::Material* material = new osg::Material;
     material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
-    material->setEmission(osg::Material::FRONT_AND_BACK,
-                          osg::Vec4(0, 0, 0, 1));
-    material->setSpecular(osg::Material::FRONT_AND_BACK,
-                          osg::Vec4(0, 0, 0, 1));
-    stateSet->setAttributeAndModes(material);
+    material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,1));
+    material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,1));
+    stateSet->setAttribute(material);
 
     osg::ShadeModel* shadeModel = new osg::ShadeModel;
-    shadeModel->setMode(osg::ShadeModel::FLAT);
+    shadeModel->setMode(osg::ShadeModel::SMOOTH);
     stateSet->setAttributeAndModes(shadeModel);
 
     osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
-    alphaFunc->setFunction(osg::AlphaFunc::GREATER);
-    alphaFunc->setReferenceValue(0.01);
+    alphaFunc->setFunction(osg::AlphaFunc::ALWAYS);
     stateSet->setAttributeAndModes(alphaFunc);
 
     osg::BlendFunc* blendFunc = new osg::BlendFunc;
@@ -101,21 +104,22 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
     stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
     stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
 
-
     osg::Geode* geode = new osg::Geode;
     stateSet = geode->getOrCreateStateSet();
 
-    stateSet->setRenderBinDetails(-8, "RenderBin");
+    stateSet->setRenderBinDetails(-6, "RenderBin");
 
     // set up the sun-state
-    path.append( "sun.rgba" );
-    osg::Texture2D* texture = SGLoadTexture2D(path);
+    osg::Texture2D* texture = SGLoadTexture2D("sun.png", options.get());
     stateSet->setTextureAttributeAndModes(0, texture);
 
     // Build scenegraph
     sun_cl = new osg::Vec4Array;
     sun_cl->push_back(osg::Vec4(1, 1, 1, 1));
 
+    scene_cl = new osg::Vec4Array;
+    scene_cl->push_back(osg::Vec4(1, 1, 1, 1));
+
     osg::Vec3Array* sun_vl = new osg::Vec3Array;
     sun_vl->push_back(osg::Vec3(-sun_size, 0, -sun_size));
     sun_vl->push_back(osg::Vec3(sun_size, 0, -sun_size));
@@ -133,20 +137,19 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
     geometry->setVertexArray(sun_vl);
     geometry->setColorArray(sun_cl.get());
     geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+    geometry->setNormalBinding(osg::Geometry::BIND_OFF);
     geometry->setTexCoordArray(0, sun_tl);
     geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4));
     geode->addDrawable(geometry);
 
     sun_transform->addChild( geode );
 
-
     // set up the inner-halo state
     geode = new osg::Geode;
     stateSet = geode->getOrCreateStateSet();
     stateSet->setRenderBinDetails(-7, "RenderBin");
     
-    ihalopath.append( "inner_halo.rgba" );
-    texture = SGLoadTexture2D(path);
+    texture = SGLoadTexture2D("inner_halo.png", options.get());
     stateSet->setTextureAttributeAndModes(0, texture);
 
     // Build ssg structure
@@ -171,28 +174,27 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
     geometry->setVertexArray(ihalo_vl);
     geometry->setColorArray(ihalo_cl.get());
     geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+    geometry->setNormalBinding(osg::Geometry::BIND_OFF);
     geometry->setTexCoordArray(0, ihalo_tl);
     geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4));
     geode->addDrawable(geometry);
 
     sun_transform->addChild( geode );
-
     
     // set up the outer halo state
     
     geode = new osg::Geode;
     stateSet = geode->getOrCreateStateSet();
-    stateSet->setRenderBinDetails(-6, "RenderBin");
+    stateSet->setRenderBinDetails(-8, "RenderBin");
 
-    ohalopath.append( "outer_halo.rgba" );
-    texture = SGLoadTexture2D(path);
+    texture = SGLoadTexture2D("outer_halo.png", options.get());
     stateSet->setTextureAttributeAndModes(0, texture);
 
     // Build ssg structure
     ohalo_cl = new osg::Vec4Array;
     ohalo_cl->push_back(osg::Vec4(1, 1, 1, 1));
 
-    double ohalo_size = sun_size * 7.0;
+    double ohalo_size = sun_size * 8.0;
     osg::Vec3Array* ohalo_vl = new osg::Vec3Array;
     ohalo_vl->push_back(osg::Vec3(-ohalo_size, 0, -ohalo_size));
     ohalo_vl->push_back(osg::Vec3(ohalo_size, 0, -ohalo_size));
@@ -207,16 +209,16 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
 
     geometry = new osg::Geometry;
     geometry->setUseDisplayList(false);
-    geometry->setVertexArray(ihalo_vl);
-    geometry->setColorArray(ihalo_cl.get());
+    geometry->setVertexArray(ohalo_vl);
+    geometry->setColorArray(ohalo_cl.get());
     geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
-    geometry->setTexCoordArray(0, ihalo_tl);
+    geometry->setNormalBinding(osg::Geometry::BIND_OFF);
+    geometry->setTexCoordArray(0, ohalo_tl);
     geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP, 0, 4));
     geode->addDrawable(geometry);
 
     sun_transform->addChild( geode );
 
-
     // force a repaint of the sun colors with arbitrary defaults
     repaint( 0.0, 1.0 );
 
@@ -230,127 +232,126 @@ SGSun::build( SGPath path, double sun_size, SGPropertyNode *property_tree_Node )
 // 90 degrees = sun rise/set
 // 180 degrees = darkest midnight
 bool SGSun::repaint( double sun_angle, double new_visibility ) {
-    
-       if ( visibility != new_visibility ) {
-               visibility = new_visibility;
-
-               static const double sqrt_m_log01 = sqrt( -log( 0.01 ) );
-               sun_exp2_punch_through = sqrt_m_log01 / ( visibility * 15 );
-       }
-
-       if ( prev_sun_angle != sun_angle ) {
-               prev_sun_angle = sun_angle;
-
-               // determine how much aerosols are in the air (rough guess)
-               double aerosol_factor;
-               if ( visibility < 100 ){
-                       aerosol_factor = 8000;
-               }
-               else {
-                       aerosol_factor = 80.5 / log( visibility / 100 );
-               }
-
-               // get environmental data from property tree or use defaults
-               double rel_humidity, density_avg;
-
-               if ( !env_node )
-               {
-                       rel_humidity = 0.5;
-                       density_avg = 0.7;
-               }
-               else
-               {
-                       rel_humidity = env_node->getFloatValue( "relative-humidity" ); 
-                       density_avg =  env_node->getFloatValue( "atmosphere/density-tropo-avg" );
-               }
-
-               // ok, now let's go and generate the sun color
-                osg::Vec4 i_halo_color, o_halo_color, sun_color;
-
-               // Some comments: 
-               // When the sunangle changes, light has to travel a longer distance through the atmosphere.
-               // So it's scattered more due to raleigh scattering, which affects blue more than green light.
-               // Red is almost not scattered and effectively only get's touched when the sun is near the horizon.
-               // Visability also affects suncolor inasmuch as more particles are in the air that cause more scattering.
-               // We base our calculation on the halo's color, which is most scattered. 
-               // Red - is almost not scattered        
-               // Lambda is 700 nm
-               
-               double red_scat_f = ( aerosol_factor * path_distance * density_avg ) / 5E+07;
-               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 );
-
-               // Green - 546.1 nm
-               double green_scat_f = ( aerosol_factor * path_distance * density_avg ) / 8.8938E+06;
-               sun_color[1] = 1 - green_scat_f;
-               i_halo_color[1] = 1 - ( 1.1 * green_scat_f );
-               o_halo_color[1] = 1 - ( 1.4 * green_scat_f );
-               // Blue - 435.8 nm
-               double blue_scat_f = ( aerosol_factor * path_distance * density_avg ) / 3.607E+06;
-               sun_color[2] = 1 - blue_scat_f;
-               i_halo_color[2] = 1 - ( 1.1 * blue_scat_f );
-               o_halo_color[2] = 1 - ( 1.4 * blue_scat_f );
-
-               // Alpha
-               sun_color[3] = 1;
-               i_halo_color[3] = 1;
-
-               o_halo_color[3] = blue_scat_f; 
-               if ( ( new_visibility < 10000 ) &&  ( blue_scat_f > 1 )){
-                       o_halo_color[3] = 2 - blue_scat_f; 
-               }
-
-
-               // Now that we have the color calculated 
-               // let's consider the saturation which is produced by mie scattering
-               double saturation = 1 - ( rel_humidity / 200 );
-               sun_color[1] += (( 1 - saturation ) * ( 1 - sun_color[1] ));
-               sun_color[2] += (( 1 - saturation ) * ( 1 - sun_color[2] ));
-
-               i_halo_color[1] += (( 1 - saturation ) * ( 1 - i_halo_color[1] ));
-               i_halo_color[2] += (( 1 - saturation ) * ( 1 - i_halo_color[2] )); 
-
-               o_halo_color[1] += (( 1 - saturation ) * ( 1 - o_halo_color[1] )); 
-               o_halo_color[2] += (( 1 - saturation ) * ( 1 - o_halo_color[2] )); 
-
-               // just to make sure we're in the limits
-               if ( sun_color[0] < 0 ) sun_color[0] = 0;
-               else if ( sun_color[0] > 1) sun_color[0] = 1;
-               if ( i_halo_color[0] < 0 ) i_halo_color[0] = 0;
-               else if ( i_halo_color[0] > 1) i_halo_color[0] = 1;
-               if ( o_halo_color[0] < 0 ) o_halo_color[0] = 0;
-               else if ( o_halo_color[0] > 1) o_halo_color[0] = 1;
-
-               if ( sun_color[1] < 0 ) sun_color[1] = 0;
-               else if ( sun_color[1] > 1) sun_color[1] = 1;
-               if ( i_halo_color[1] < 0 ) i_halo_color[1] = 0;
-               else if ( i_halo_color[1] > 1) i_halo_color[1] = 1;
-               if ( o_halo_color[1] < 0 ) o_halo_color[1] = 0;
-               else if ( o_halo_color[1] > 1) o_halo_color[1] = 1;
-
-               if ( sun_color[2] < 0 ) sun_color[2] = 0;
-               else if ( sun_color[2] > 1) sun_color[2] = 1;
-               if ( i_halo_color[2] < 0 ) i_halo_color[2] = 0;
-               else if ( i_halo_color[2] > 1) i_halo_color[2] = 1;
-               if ( o_halo_color[2] < 0 ) o_halo_color[2] = 0;
-               else if ( o_halo_color[2] > 1) o_halo_color[2] = 1;
-               if ( o_halo_color[3] < 0 ) o_halo_color[2] = 0;
-               else if ( o_halo_color[3] > 1) o_halo_color[3] = 1;
 
+    if ( visibility != new_visibility ) {
+        if (new_visibility < 100.0) new_visibility = 100.0;
+        else if (new_visibility > 45000.0) new_visibility = 45000.0;
+        visibility = new_visibility;
+        sun_exp2_punch_through = 2.0/log(visibility);
+    }
+
+    if ( prev_sun_angle != sun_angle ) {
+        prev_sun_angle = sun_angle;
+
+        // determine how much aerosols are in the air (rough guess)
+        double aerosol_factor;
+        if ( visibility < 100 ) {
+            aerosol_factor = 8000;
+        }
+        else {
+            aerosol_factor = 80.5 / log( visibility / 99.9 );
+        }
+
+        // get environmental data from property tree or use defaults
+        double rel_humidity, density_avg;
+
+        if ( !env_node ) {
+            rel_humidity = 0.5;
+            density_avg = 0.7;
+        }
+        else {
+            rel_humidity = env_node->getFloatValue( "relative-humidity" ); 
+            density_avg =  env_node->getFloatValue( "atmosphere/density-tropo-avg" );
+        }
+
+        // ok, now let's go and generate the sun and scene color
+        osg::Vec4 i_halo_color, o_halo_color, scene_color, sun_color;
+
+        // Some comments: 
+        // * When the sunangle changes, light has to travel a longer
+        //   distance through the atmosphere. So it's scattered more due
+        //   to raleigh scattering, which affects blue more than green
+        //   light.
+        // * Red is almost not scattered and effectively only get's
+        //   touched when the sun is near the horizon.
+        // * Visability also affects suncolor inasmuch as more particles
+        //   are in the air that cause more scattering.
+        // * We base our calculation on the halo's color, which is most
+        //   scattered. 
+        double red_scat_f, red_scat_corr_f, green_scat_f, blue_scat_f;
+        // Red - is almost not scattered     
+        // Lambda is 700 nm
         
-               gamma_correct_rgb( i_halo_color._v );
-               gamma_correct_rgb( o_halo_color._v );
-               gamma_correct_rgb( sun_color._v );      
-
-               (*sun_cl)[0] = sun_color;
-                sun_cl->dirty();
-               (*ihalo_cl)[0] = i_halo_color;
-                ihalo_cl->dirty();
-               (*ohalo_cl)[0] = o_halo_color;
-                ohalo_cl->dirty();
+        red_scat_f = (aerosol_factor * path_distance * density_avg)/5E+07;
+        red_scat_corr_f = sun_exp2_punch_through / (1 - red_scat_f);
+        sun_color[0] = 1;
+        scene_color[0] = 1 - red_scat_f;
+
+        // Green - 546.1 nm
+        green_scat_f = (aerosol_factor * path_distance * density_avg)/8.8938E+06;
+        sun_color[1] = 1 - green_scat_f * red_scat_corr_f;
+        scene_color[1] = 1 - green_scat_f;
+        // Blue - 435.8 nm
+        blue_scat_f = (aerosol_factor * path_distance * density_avg)/3.607E+06;
+        sun_color[2] = 1 - blue_scat_f * red_scat_corr_f;
+        scene_color[2] = 1 - blue_scat_f;
+
+        // Alpha
+        sun_color[3] = 1;
+        scene_color[3] = 1;
+
+        // Now that we have the color calculated 
+        // let's consider the saturation which is produced by mie scattering
+        double saturation = 1 - ( rel_humidity / 200 );
+        scene_color[1] += (( 1 - saturation ) * ( 1 - scene_color[1] ));
+        scene_color[2] += (( 1 - saturation ) * ( 1 - scene_color[2] ));
+
+        if (sun_color[0] > 1.0) sun_color[0] = 1.0;
+        if (sun_color[0] < 0.0) sun_color[0] = 0.0;
+        if (sun_color[1] > 1.0) sun_color[1] = 1.0;
+        if (sun_color[1] < 0.0) sun_color[1] = 0.0;
+        if (sun_color[2] > 1.0) sun_color[2] = 1.0;
+        if (sun_color[2] < 0.0) sun_color[2] = 0.0;
+
+        if (scene_color[0] > 1.0) scene_color[0] = 1.0;
+        if (scene_color[0] < 0.0) scene_color[0] = 0.0;
+        if (scene_color[1] > 1.0) scene_color[1] = 1.0;
+        if (scene_color[1] < 0.0) scene_color[1] = 0.0;
+        if (scene_color[2] > 1.0) scene_color[2] = 1.0;
+        if (scene_color[2] < 0.0) scene_color[2] = 0.0;
+
+        double scene_f = 0.5 * (1 / (1 - red_scat_f));
+        double sun_f = 1.0 - scene_f;
+        i_halo_color[0] = sun_f * sun_color[0] + scene_f * scene_color[0];
+        i_halo_color[1] = sun_f * sun_color[1] + scene_f * scene_color[1];
+        i_halo_color[2] = sun_f * sun_color[2] + scene_f * scene_color[2];
+        i_halo_color[3] = 1;
+
+        o_halo_color[0] = 0.2 * sun_color[0] + 0.8 * scene_color[0];
+        o_halo_color[1] = 0.2 * sun_color[1] + 0.8 * scene_color[1];
+        o_halo_color[2] = 0.2 * sun_color[2] + 0.8 * scene_color[2];
+        o_halo_color[3] = blue_scat_f;
+        if ((visibility < 10000) && (blue_scat_f > 1)) {
+            o_halo_color[3] = 2 - blue_scat_f;
+        }
+        if (o_halo_color[3] > 1) o_halo_color[3] = 1;
+        if (o_halo_color[3] < 0) o_halo_color[3] = 0;
+
+        gamma_correct_rgb( i_halo_color._v );
+        gamma_correct_rgb( o_halo_color._v );
+        gamma_correct_rgb( scene_color._v );    
+        gamma_correct_rgb( sun_color._v );
+
+        (*sun_cl)[0] = sun_color;
+        sun_cl->dirty();
+        (*scene_cl)[0] = scene_color;
+        scene_cl->dirty();
+        (*ihalo_cl)[0] = i_halo_color;
+        ihalo_cl->dirty();
+        (*ohalo_cl)[0] = o_halo_color;
+        ohalo_cl->dirty();
     }
 
     return true;
@@ -362,15 +363,11 @@ bool SGSun::repaint( double sun_angle, double new_visibility ) {
 // fixed at a great distance from the viewer.  Also add in an optional
 // rotation (i.e. for the current time of day.)
 // Then calculate stuff needed for the sun-coloring
-bool SGSun::reposition( const SGVec3f& p, double angle,
-                       double rightAscension, double declination, 
-                       double sun_dist, double lat, double alt_asl, double sun_angle)
+bool SGSun::reposition( double rightAscension, double declination, 
+                        double sun_dist, double lat, double alt_asl, double sun_angle)
 {
     // GST - GMT sidereal time 
-    osg::Matrix T1, T2, GST, RA, DEC;
-
-    T1.makeTranslate(p.osg());
-    GST.makeRotate(SGD_DEGREES_TO_RADIANS*angle, osg::Vec3(0, 0, -1));
+    osg::Matrix T2, RA, DEC;
 
     // xglRotatef( ((SGD_RADIANS_TO_DEGREES * rightAscension)- 90.0),
     //             0.0, 0.0, 1.0);
@@ -382,7 +379,7 @@ bool SGSun::reposition( const SGVec3f& p, double angle,
     // xglTranslatef(0,sun_dist);
     T2.makeTranslate(osg::Vec3(0, sun_dist, 0));
 
-    sun_transform->setMatrix(T2*DEC*RA*GST*T1);
+    sun_transform->setMatrix(T2*DEC*RA);
 
     // Suncolor related things:
     if ( prev_sun_angle != sun_angle ) {
@@ -399,6 +396,7 @@ bool SGSun::reposition( const SGVec3f& p, double angle,
 
          double gamma =  SG_PI - sun_angle;
          double sin_beta =  ( position_radius * sin ( gamma )  ) / r_tropo;
+         if (sin_beta > 1.0) sin_beta = 1.0;
          double alpha =  SG_PI - gamma - asin( sin_beta );
 
          // OK, now let's calculate the distance the light travels
@@ -424,3 +422,9 @@ SGSun::get_color()
 {
     return SGVec4f((*sun_cl)[0][0], (*sun_cl)[0][1], (*sun_cl)[0][2], (*sun_cl)[0][3]);
 }
+
+SGVec4f
+SGSun::get_scene_color()
+{
+    return SGVec4f((*scene_cl)[0][0], (*scene_cl)[0][1], (*scene_cl)[0][2], (*scene_cl)[0][3]);
+}