]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/renderer.cxx
Fix shared library build for metar executable
[flightgear.git] / src / Main / renderer.cxx
index fe713ab623984fb917862e9263b7683e85f7d8dd..48b22841cef5411dbed1612966f38604ab51eda4 100644 (file)
@@ -93,6 +93,7 @@
 #include <GUI/new_gui.hxx>
 #include <Instrumentation/HUD/HUD.hxx>
 #include <Environment/precipitation_mgr.hxx>
+#include <Environment/environment_mgr.hxx>
 
 #include "splash.hxx"
 #include "renderer.hxx"
@@ -128,7 +129,7 @@ public:
       hint->setMode(GL_DONT_CARE);
   }
 private:
-  SGSharedPtr<SGPropertyNode> mConfigNode;
+  SGPropertyNode_ptr mConfigNode;
 };
 
 
@@ -272,7 +273,7 @@ private:
 class FGWireFrameModeUpdateCallback : public osg::StateAttribute::Callback {
 public:
   FGWireFrameModeUpdateCallback() :
-    mWireframe(fgGetNode("/sim/rendering/wireframe"))
+    mWireframe(fgGetNode("/sim/rendering/wireframe", true))
   { }
   virtual void operator()(osg::StateAttribute* stateAttribute,
                           osg::NodeVisitor*)
@@ -289,13 +290,13 @@ public:
                            osg::PolygonMode::FILL);
   }
 private:
-  SGSharedPtr<SGPropertyNode> mWireframe;
+  SGPropertyNode_ptr mWireframe;
 };
 
 class FGLightModelUpdateCallback : public osg::StateAttribute::Callback {
 public:
   FGLightModelUpdateCallback() :
-    mHighlights(fgGetNode("/sim/rendering/specular-highlight"))
+    mHighlights(fgGetNode("/sim/rendering/specular-highlight", true))
   { }
   virtual void operator()(osg::StateAttribute* stateAttribute,
                           osg::NodeVisitor*)
@@ -320,13 +321,13 @@ public:
     }
   }
 private:
-  SGSharedPtr<SGPropertyNode> mHighlights;
+  SGPropertyNode_ptr mHighlights;
 };
 
 class FGFogEnableUpdateCallback : public osg::StateSet::Callback {
 public:
   FGFogEnableUpdateCallback() :
-    mFogEnabled(fgGetNode("/sim/rendering/fog"))
+    mFogEnabled(fgGetNode("/sim/rendering/fog", true))
   { }
   virtual void operator()(osg::StateSet* stateSet, osg::NodeVisitor*)
   {
@@ -337,7 +338,7 @@ public:
     }
   }
 private:
-  SGSharedPtr<SGPropertyNode> mFogEnabled;
+  SGPropertyNode_ptr mFogEnabled;
 };
 
 class FGFogUpdateCallback : public osg::StateAttribute::Callback {
@@ -362,17 +363,17 @@ public:
     assert(dynamic_cast<osg::Switch*>(node));
     osg::Switch* sw = static_cast<osg::Switch*>(node);
 
-    double t = globals->get_sim_time_sec();
-    bool enabled = 0 < t;
+    bool enabled = scenery_enabled;
     sw->setValue(0, enabled);
     if (!enabled)
       return;
     traverse(node, nv);
   }
+
+  static bool scenery_enabled;
 };
 
-// Sky structures
-SGSky *thesky;
+bool FGScenerySwitchCallback::scenery_enabled = false;
 
 static osg::ref_ptr<osg::FrameStamp> mFrameStamp = new osg::FrameStamp;
 static osg::ref_ptr<SGUpdateVisitor> mUpdateVisitor= new SGUpdateVisitor;
@@ -381,10 +382,18 @@ static osg::ref_ptr<osg::Group> mRealRoot = new osg::Group;
 
 static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
 
-FGRenderer::FGRenderer()
+#ifdef FG_JPEG_SERVER
+static void updateRenderer()
+{
+    globals->get_renderer()->update();
+}
+#endif
+
+FGRenderer::FGRenderer() :
+    _sky(NULL)
 {
 #ifdef FG_JPEG_SERVER
-   jpgRenderFrame = FGRenderer::update;
+   jpgRenderFrame = updateRenderer;
 #endif
    eventHandler = new FGEventHandler;
 }
@@ -394,6 +403,7 @@ FGRenderer::~FGRenderer()
 #ifdef FG_JPEG_SERVER
    jpgRenderFrame = NULL;
 #endif
+    delete _sky;
 }
 
 // Initialize various GL/view parameters
@@ -401,7 +411,7 @@ FGRenderer::~FGRenderer()
 // critical parts of the scene graph in addition to the splash screen.
 void
 FGRenderer::splashinit( void ) {
-    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+    osgViewer::Viewer* viewer = getViewer();
     mRealRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
     mRealRoot->addChild(fgCreateSplashNode());
     mFrameStamp = viewer->getFrameStamp();
@@ -409,10 +419,59 @@ FGRenderer::splashinit( void ) {
     // visitor automatically.
     mUpdateVisitor->setFrameStamp(mFrameStamp.get());
     viewer->setUpdateVisitor(mUpdateVisitor.get());
+    fgSetDouble("/sim/startup/splash-alpha", 1.0);
 }
 
 void
 FGRenderer::init( void )
+{
+    _scenery_loaded   = fgGetNode("/sim/sceneryloaded", true);
+    _scenery_override = fgGetNode("/sim/sceneryloaded-override", true);
+    _panel_hotspots   = fgGetNode("/sim/panel-hotspots", true);
+    _virtual_cockpit  = fgGetNode("/sim/virtual-cockpit", true);
+
+    _sim_delta_sec = fgGetNode("/sim/time/delta-sec", true);
+
+    _xsize         = fgGetNode("/sim/startup/xsize", true);
+    _ysize         = fgGetNode("/sim/startup/ysize", true);
+    _splash_alpha  = fgGetNode("/sim/startup/splash-alpha", true);
+
+    _skyblend             = fgGetNode("/sim/rendering/skyblend", true);
+    _point_sprites        = fgGetNode("/sim/rendering/point-sprites", true);
+    _enhanced_lighting    = fgGetNode("/sim/rendering/enhanced-lighting", true);
+    _distance_attenuation = fgGetNode("/sim/rendering/distance-attenuation", true);
+    _horizon_effect       = fgGetNode("/sim/rendering/horizon-effect", true);
+    _textures             = fgGetNode("/sim/rendering/textures", true);
+
+    _altitude_ft = fgGetNode("/position/altitude-ft", true);
+
+    _cloud_status = fgGetNode("/environment/clouds/status", true);
+    _visibility_m = fgGetNode("/environment/visibility-m", true);
+    
+    bool use_point_sprites = _point_sprites->getBoolValue();
+    bool enhanced_lighting = _enhanced_lighting->getBoolValue();
+    bool distance_attenuation = _distance_attenuation->getBoolValue();
+
+    SGConfigureDirectionalLights( use_point_sprites, enhanced_lighting,
+                                  distance_attenuation );
+    
+// create sky, but can't build until setupView, since we depend
+// on other subsystems to be inited, eg Ephemeris    
+    _sky = new SGSky;
+    
+    SGPath texture_path(globals->get_fg_root());
+    texture_path.append("Textures");
+    texture_path.append("Sky");
+    for (int i = 0; i < FGEnvironmentMgr::MAX_CLOUD_LAYERS; i++) {
+        SGCloudLayer * layer = new SGCloudLayer(texture_path.str());
+        _sky->add_cloud_layer(layer);
+    }
+    
+    _sky->texture_path( texture_path.str() );
+}
+
+void
+FGRenderer::setupView( void )
 {
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
     osg::initNotifyLevel();
@@ -427,6 +486,17 @@ FGRenderer::init( void )
     if ( fgGetBool("/sim/startup/fullscreen") )
         fgOSFullScreen();
 
+// build the sky    
+    // The sun and moon diameters are scaled down numbers of the
+    // actual diameters. This was needed to fit both the sun and the
+    // moon within the distance to the far clip plane.
+    // Moon diameter:    3,476 kilometers
+    // Sun diameter: 1,390,000 kilometers
+    _sky->build( 80000.0, 80000.0,
+                  463.3, 361.8,
+                  *globals->get_ephem(),
+                  fgGetNode("/environment", true));
+    
     viewer->getCamera()
         ->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
     
@@ -502,15 +572,17 @@ FGRenderer::init( void )
     sunLight->setUpdateCallback(new FGLightSourceUpdateCallback(true));
     sunLight->setReferenceFrame(osg::LightSource::RELATIVE_RF);
     sunLight->setLocalStateSetModes(osg::StateAttribute::ON);
+    
     // Hang a StateSet above the sky subgraph in order to turn off
     // light 0
     Group* skyGroup = new Group;
     StateSet* skySS = skyGroup->getOrCreateStateSet();
     skySS->setMode(GL_LIGHT0, StateAttribute::OFF);
-    skyGroup->addChild(thesky->getPreRoot());
+    skyGroup->addChild(_sky->getPreRoot());
     sunLight->addChild(skyGroup);
     mRoot->addChild(sceneGroup);
     mRoot->addChild(sunLight);
+    
     // Clouds are added to the scene graph later
     stateSet = globals->get_scenery()->get_scene_graph()->getOrCreateStateSet();
     stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
@@ -549,7 +621,7 @@ FGRenderer::init( void )
     // The clouds are attached directly to the scene graph root
     // because, in theory, they don't want the same default state set
     // as the rest of the scene. This may not be true in practice.
-    mRealRoot->addChild(thesky->getCloudRoot());
+    mRealRoot->addChild(_sky->getCloudRoot());
     mRealRoot->addChild(FGCreateRedoutNode());
     // Attach empty program to the scene root so that shader programs
     // don't leak into state sets (effects) that shouldn't have one.
@@ -557,39 +629,51 @@ FGRenderer::init( void )
     stateSet->setAttributeAndModes(new osg::Program, osg::StateAttribute::ON);
 }
 
-
 // Update all Visuals (redraws anything graphics related)
 void
-FGRenderer::update( bool refresh_camera_settings ) {
-    bool scenery_loaded = fgGetBool("sim/sceneryloaded", false)
-                          || fgGetBool("sim/sceneryloaded-override");
-    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
-    if (!scenery_loaded) {
-      fgSetDouble("/sim/startup/splash-alpha", 1.0);
-      return;
+FGRenderer::update( ) {
+    if (!(_scenery_loaded->getBoolValue() || 
+           _scenery_override->getBoolValue()))
+    {
+        _splash_alpha->setDoubleValue(1.0);
+        return;
     }
+    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
 
-    // Fade out the splash screen over the first three seconds.
-    double sAlpha = SGMiscd::max(0, (2.5 - globals->get_sim_time_sec()) / 2.5);
-    fgSetDouble("/sim/startup/splash-alpha", sAlpha);
+    if (_splash_alpha->getDoubleValue()>0.0)
+    {
+        // Fade out the splash screen
+        const double fade_time = 0.8;
+        const double fade_steps_per_sec = 20;
+        double delay_time = SGMiscd::min(fade_time/fade_steps_per_sec,
+                                         (SGTimeStamp::now() - _splash_time).toSecs());
+        _splash_time = SGTimeStamp::now();
+        double sAlpha = _splash_alpha->getDoubleValue();
+        sAlpha -= SGMiscd::max(0.0,delay_time/fade_time);
+        FGScenerySwitchCallback::scenery_enabled = (sAlpha<1.0);
+        _splash_alpha->setDoubleValue(sAlpha);
+    }
 
-    bool skyblend = fgGetBool("/sim/rendering/skyblend");
-    bool use_point_sprites = fgGetBool("/sim/rendering/point-sprites");
-    bool enhanced_lighting = fgGetBool("/sim/rendering/enhanced-lighting");
-    bool distance_attenuation
-        = fgGetBool("/sim/rendering/distance-attenuation");
-    // OSGFIXME
-    SGConfigureDirectionalLights( use_point_sprites, enhanced_lighting,
-                                  distance_attenuation );
+#if 0 // OSGFIXME
+    // OSGFIXME: features no longer available or no longer run-time configurable
+    {
+        bool use_point_sprites = _point_sprites->getBoolValue();
+        bool enhanced_lighting = _enhanced_lighting->getBoolValue();
+        bool distance_attenuation = _distance_attenuation->getBoolValue();
+    
+        SGConfigureDirectionalLights( use_point_sprites, enhanced_lighting,
+                                      distance_attenuation );
+    }
+#endif
 
     FGLight *l = static_cast<FGLight*>(globals->get_subsystem("lighting"));
 
     // update fog params
     double actual_visibility;
-    if (fgGetBool("/environment/clouds/status")) {
-        actual_visibility = thesky->get_visibility();
+    if (_cloud_status->getBoolValue()) {
+        actual_visibility = _sky->get_visibility();
     } else {
-        actual_visibility = fgGetDouble("/environment/visibility-m");
+        actual_visibility = _visibility_m->getDoubleValue();
     }
 
     // idle_state is now 1000 meaning we've finished all our
@@ -599,31 +683,27 @@ FGRenderer::update( bool refresh_camera_settings ) {
     FGViewer *current__view = globals->get_current_view();
     // Force update of center dependent values ...
     current__view->set_dirty();
-
-    if ( refresh_camera_settings ) {
-        // update view port
-        resize( fgGetInt("/sim/startup/xsize"),
-                fgGetInt("/sim/startup/ysize") );
-    }
+  
     osg::Camera *camera = viewer->getCamera();
 
+    bool skyblend = _skyblend->getBoolValue();
     if ( skyblend ) {
        
-        if ( fgGetBool("/sim/rendering/textures") ) {
+        if ( _textures->getBoolValue() ) {
             SGVec4f clearColor(l->adj_fog_color());
-            camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
+            camera->setClearColor(toOsg(clearColor));
         }
     } else {
         SGVec4f clearColor(l->sky_color());
-        camera->setClearColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
+        camera->setClearColor(toOsg(clearColor));
     }
 
     // update fog params if visibility has changed
-    double visibility_meters = fgGetDouble("/environment/visibility-m");
-    thesky->set_visibility(visibility_meters);
+    double visibility_meters = _visibility_m->getDoubleValue();
+    _sky->set_visibility(visibility_meters);
 
-    double altitude_m = fgGetDouble("/position/altitude-ft") * SG_FEET_TO_METER;
-    thesky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
+    double altitude_m = _altitude_ft->getDoubleValue() * SG_FEET_TO_METER;
+    _sky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
 
     // update the sky dome
     if ( skyblend ) {
@@ -635,7 +715,7 @@ FGRenderer::update( bool refresh_camera_settings ) {
         // Sun distance: 150,000,000 kilometers
 
         double sun_horiz_eff, moon_horiz_eff;
-        if (fgGetBool("/sim/rendering/horizon-effect")) {
+        if (_horizon_effect->getBoolValue()) {
             sun_horiz_eff
                 = 0.67 + pow(osg::clampAbove(0.5 + cos(l->get_sun_angle()),
                                              0.0),
@@ -666,9 +746,9 @@ FGRenderer::update( bool refresh_camera_settings ) {
         scolor.sun_angle   = l->get_sun_angle();
         scolor.moon_angle  = l->get_moon_angle();
   
-        double delta_time_sec = fgGetDouble("/sim/time/delta-sec");
-        thesky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
-        thesky->repaint( scolor, *globals->get_ephem() );
+        double delta_time_sec = _sim_delta_sec->getDoubleValue();
+        _sky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
+        _sky->repaint( scolor, *globals->get_ephem() );
 
             //OSGFIXME
 //         shadows->setupShadows(
@@ -712,45 +792,23 @@ FGRenderer::update( bool refresh_camera_settings ) {
                              l->get_sun_angle()*SGD_RADIANS_TO_DEGREES);
     mUpdateVisitor->setVisibility(actual_visibility);
     simgear::GroundLightManager::instance()->update(mUpdateVisitor.get());
-    bool hotspots = fgGetBool("/sim/panel-hotspots");
     osg::Node::NodeMask cullMask = ~simgear::LIGHTS_BITS & ~simgear::PICK_BIT;
     cullMask |= simgear::GroundLightManager::instance()
         ->getLightNodeMask(mUpdateVisitor.get());
-    if (hotspots)
+    if (_panel_hotspots->getBoolValue())
         cullMask |= simgear::PICK_BIT;
     CameraGroup::getDefault()->setCameraCullMasks(cullMask);
 }
 
-
-
-// options.cxx needs to see this for toggle_panel()
-// Handle new window size or exposure
 void
-FGRenderer::resize( int width, int height ) {
-    int view_h;
-
-    if ( (!fgGetBool("/sim/virtual-cockpit"))
-         && fgPanelVisible() && idle_state == 1000 ) {
-        view_h = (int)(height * (globals->get_current_panel()->getViewHeight() -
-                             globals->get_current_panel()->getYOffset()) / 768.0);
-    } else {
-        view_h = height;
-    }
-
-    static int lastwidth = 0;
-    static int lastheight = 0;
-    if (width != lastwidth)
-        fgSetInt("/sim/startup/xsize", lastwidth = width);
-    if (height != lastheight)
-        fgSetInt("/sim/startup/ysize", lastheight = height);
-
-    // for all views
-    FGViewMgr *viewmgr = globals->get_viewmgr();
-    if (viewmgr) {
-      for ( int i = 0; i < viewmgr->size(); ++i ) {
-        viewmgr->get_view(i)->
-          set_aspect_ratio((float)view_h / (float)width);
-      }
+FGRenderer::resize( int width, int height )
+{
+    int curWidth = _xsize->getIntValue(),
+        curHeight = _ysize->getIntValue();
+    if ((curHeight != height) || (curWidth != width)) {
+    // must guard setting these, or PLIB-PUI fails with too many live interfaces
+        _xsize->setIntValue(width);
+        _ysize->setIntValue(height);
     }
 }