]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/renderer.cxx
Add the alpha test back in so the instruments won't disappear after changing the...
[flightgear.git] / src / Main / renderer.cxx
index 87e8932c1e2709a4ca9ccf61e296527305f5fee9..c952faed97b247241ffca1cad3f76f683b3afff1 100644 (file)
 // You should have received a copy of the GNU General Public License
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//
-// $Id$
-
 
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #endif
 
-#include <simgear/compiler.h>
-
 #ifdef HAVE_WINDOWS_H
 #  include <windows.h>
 #endif
 
+#include <simgear/compiler.h>
+
 #include <osg/ref_ptr>
 #include <osg/AlphaFunc>
 #include <osg/BlendFunc>
 #include <osg/Camera>
-#include <osg/CameraView>
 #include <osg/CullFace>
 #include <osg/Depth>
 #include <osg/Fog>
 #include <osg/Group>
+#include <osg/Hint>
 #include <osg/Light>
 #include <osg/LightModel>
 #include <osg/LightSource>
+#include <osg/Material>
 #include <osg/NodeCallback>
 #include <osg/Notify>
 #include <osg/PolygonMode>
 #include <osg/PolygonOffset>
-#include <osg/ShadeModel>
+#include <osg/Version>
 #include <osg/TexEnv>
 
-#include <osgUtil/SceneView>
-#include <osgUtil/UpdateVisitor>
-#include <osgUtil/IntersectVisitor>
 #include <osgUtil/LineSegmentIntersector>
 
 #include <osg/io_utils>
 #include <osgDB/WriteFile>
-#include <osgDB/ReadFile>
-#include <sstream>
 
 #include <simgear/math/SGMath.hxx>
 #include <simgear/screen/extensions.hxx>
 #include <simgear/scene/material/matlib.hxx>
 #include <simgear/scene/model/animation.hxx>
-#include <simgear/scene/model/model.hxx>
-#include <simgear/scene/model/modellib.hxx>
 #include <simgear/scene/model/placement.hxx>
+#include <simgear/scene/sky/sky.hxx>
 #include <simgear/scene/util/SGUpdateVisitor.hxx>
+#include <simgear/scene/util/RenderConstants.hxx>
+#include <simgear/scene/tgdb/GroundLightManager.hxx>
 #include <simgear/scene/tgdb/pt_lights.hxx>
 #include <simgear/props/props.hxx>
 #include <simgear/timing/sg_time.hxx>
@@ -80,7 +74,6 @@
 
 #include <simgear/environment/visual_enviro.hxx>
 
-#include <Scenery/tileentry.hxx>
 #include <Time/light.hxx>
 #include <Time/light.hxx>
 #include <Aircraft/aircraft.hxx>
 #include <GUI/new_gui.hxx>
 #include <Instrumentation/instrument_mgr.hxx>
 #include <Instrumentation/HUD/HUD.hxx>
+#include <Environment/precipitation_mgr.hxx>
 
+#include <Include/general.hxx>
 #include "splash.hxx"
 #include "renderer.hxx"
 #include "main.hxx"
+#include "CameraGroup.hxx"
+#include "ViewPartitionNode.hxx"
+
+// XXX Make this go away when OSG 2.2 is released.
+#if (FG_OSG_VERSION >= 21004)
+#define UPDATE_VISITOR_IN_VIEWER 1
+#endif
+
+using namespace osg;
+using namespace simgear;
+using namespace flightgear;
+
+class FGHintUpdateCallback : public osg::StateAttribute::Callback {
+public:
+  FGHintUpdateCallback(const char* configNode) :
+    mConfigNode(fgGetNode(configNode, true))
+  { }
+  virtual void operator()(osg::StateAttribute* stateAttribute,
+                          osg::NodeVisitor*)
+  {
+    assert(dynamic_cast<osg::Hint*>(stateAttribute));
+    osg::Hint* hint = static_cast<osg::Hint*>(stateAttribute);
+
+    const char* value = mConfigNode->getStringValue();
+    if (!value)
+      hint->setMode(GL_DONT_CARE);
+    else if (0 == strcmp(value, "nicest"))
+      hint->setMode(GL_NICEST);
+    else if (0 == strcmp(value, "fastest"))
+      hint->setMode(GL_FASTEST);
+    else
+      hint->setMode(GL_DONT_CARE);
+  }
+private:
+  SGSharedPtr<SGPropertyNode> mConfigNode;
+};
+
 
 class SGPuDrawable : public osg::Drawable {
 public:
@@ -126,13 +158,9 @@ public:
   { drawImplementation(*renderInfo.getState()); }
   void drawImplementation(osg::State& state) const
   {
-    if (!fgOSIsMainContext(state.getGraphicsContext()))
-      return;
-
-    state.pushStateSet(getStateSet());
-    state.apply();
     state.setActiveTextureUnit(0);
     state.setClientActiveTextureUnit(0);
+
     state.disableAllVertexArrays();
 
     glPushAttrib(GL_ALL_ATTRIB_BITS);
@@ -142,11 +170,6 @@ public:
 
     glPopClientAttrib();
     glPopAttrib();
-
-    state.popStateSet();
-    state.dirtyAllModes();
-    state.dirtyAllAttributes();
-    state.dirtyAllVertexArrays();
   }
 
   virtual osg::Object* cloneType() const { return new SGPuDrawable; }
@@ -178,12 +201,6 @@ public:
   { drawImplementation(*renderInfo.getState()); }
   void drawImplementation(osg::State& state) const
   {
-//     std::cout << state.getGraphicsContext() << std::endl;
-    if (!fgOSIsMainContext(state.getGraphicsContext()))
-      return;
-
-    state.pushStateSet(getStateSet());
-    state.apply();
     state.setActiveTextureUnit(0);
     state.setClientActiveTextureUnit(0);
     state.disableAllVertexArrays();
@@ -207,10 +224,6 @@ public:
     glPopClientAttrib();
     glPopAttrib();
 
-    state.popStateSet();
-    state.dirtyAllModes();
-    state.dirtyAllAttributes();
-    state.dirtyAllVertexArrays();
   }
 
   virtual osg::Object* cloneType() const { return new SGHUDAndPanelDrawable; }
@@ -350,7 +363,6 @@ public:
 // Sky structures
 SGSky *thesky;
 
-osg::ref_ptr<osgUtil::SceneView> sceneView = new osgUtil::SceneView;  // This SceneView is used by class FGJpegHttpd ( jpg-httpd.cxx )
 static osg::ref_ptr<osg::FrameStamp> mFrameStamp = new osg::FrameStamp;
 static osg::ref_ptr<SGUpdateVisitor> mUpdateVisitor= new SGUpdateVisitor;
 
@@ -358,17 +370,14 @@ static osg::ref_ptr<osg::Group> mRealRoot = new osg::Group;
 
 static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
 
-static osg::ref_ptr<osg::CameraView> mCameraView = new osg::CameraView;
-static osg::ref_ptr<osg::Camera> mBackGroundCamera = new osg::Camera;
+static osg::ref_ptr<ViewPartitionNode> viewPartition = new ViewPartitionNode;
 
 FGRenderer::FGRenderer()
 {
 #ifdef FG_JPEG_SERVER
    jpgRenderFrame = FGRenderer::update;
 #endif
-#ifdef ENABLE_OSGVIEWER
    manipulator = new FGManipulator;
-#endif   
 }
 
 FGRenderer::~FGRenderer()
@@ -384,32 +393,23 @@ FGRenderer::~FGRenderer()
 void
 FGRenderer::splashinit( void ) {
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
-    if (viewer) {
-       sceneView = 0;
-       mRealRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
-       mRealRoot->addChild(fgCreateSplashNode());
-       osgViewer::Scene* scene = viewer->getScene();
-       mFrameStamp = viewer->getFrameStamp();
-       // Scene doesn't seem to pass the frame stamp to the update
-       // visitor automatically.
-       mUpdateVisitor->setFrameStamp(mFrameStamp.get());
-       scene->setUpdateVisitor(mUpdateVisitor.get());
-    } else {
-       // Add the splash screen node
-       mRealRoot->addChild(fgCreateSplashNode());
-       sceneView->setSceneData(mRealRoot.get());
-       sceneView->setDefaults(osgUtil::SceneView::COMPILE_GLOBJECTS_AT_INIT);
-       sceneView->setFrameStamp(mFrameStamp.get());
-       sceneView->setUpdateVisitor(mUpdateVisitor.get());
-    }
+    mRealRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
+    mRealRoot->addChild(fgCreateSplashNode());
+    mFrameStamp = viewer->getFrameStamp();
+    // Scene doesn't seem to pass the frame stamp to the update
+    // visitor automatically.
+    mUpdateVisitor->setFrameStamp(mFrameStamp.get());
+#ifdef UPDATE_VISITOR_IN_VIEWER
+    viewer->setUpdateVisitor(mUpdateVisitor.get());
+#else
+    osgViewer::Scene* scene = viewer->getScene();
+    scene->setUpdateVisitor(mUpdateVisitor.get());
+#endif
 }
 
 void
-FGRenderer::init( void ) {
-    // The viewer can call this before the graphics context is current
-    // in the main thread; indeed, in a multithreaded setup it might
-    // never be current in the main thread.
-    fgMakeCurrent();
+FGRenderer::init( void )
+{
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
     osg::initNotifyLevel();
 
@@ -423,27 +423,9 @@ FGRenderer::init( void ) {
     if ( fgGetBool("/sim/startup/fullscreen") )
         fgOSFullScreen();
 
-    if ( (!strcmp(fgGetString("/sim/rendering/fog"), "disabled")) || 
-         (!fgGetBool("/sim/rendering/shading"))) {
-        // if fastest fog requested, or if flat shading force fastest
-        glHint ( GL_FOG_HINT, GL_FASTEST );
-    } else if ( !strcmp(fgGetString("/sim/rendering/fog"), "nicest") ) {
-        glHint ( GL_FOG_HINT, GL_DONT_CARE );
-    }
-
-    glHint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
-    glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
-    glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
-
-    if (viewer) {
-      viewer->getCamera()
-           ->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-    } else {
-       sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-       sceneView->getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-    }
-
-
+    viewer->getCamera()
+        ->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+    
     osg::StateSet* stateSet = mRoot->getOrCreateStateSet();
 
     stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
@@ -467,32 +449,29 @@ FGRenderer::init( void ) {
     stateSet->setTextureAttribute(0, new osg::TexEnv);
     stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF);
 
-
-//     stateSet->setAttribute(new osg::CullFace(osg::CullFace::BACK));
-//     stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
-
-    // this is the topmost scenegraph node for osg
-    mBackGroundCamera->addChild(thesky->getPreRoot());
-    mBackGroundCamera->setClearMask(0);
-
-    GLbitfield inheritanceMask = osg::CullSettings::ALL_VARIABLES;
-    inheritanceMask &= ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE;
-    inheritanceMask &= ~osg::CullSettings::NEAR_FAR_RATIO;
-    inheritanceMask &= ~osg::CullSettings::CULLING_MODE;
-    mBackGroundCamera->setInheritanceMask(inheritanceMask);
-    mBackGroundCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-    mBackGroundCamera->setCullingMode(osg::CullSettings::NO_CULLING);
-    mBackGroundCamera->setRenderOrder(osg::Camera::NESTED_RENDER);
-
-    stateSet = mBackGroundCamera->getOrCreateStateSet();
-    stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
+    osg::Hint* hint = new osg::Hint(GL_FOG_HINT, GL_DONT_CARE);
+    hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/fog"));
+    stateSet->setAttribute(hint);
+    hint = new osg::Hint(GL_POLYGON_SMOOTH_HINT, GL_DONT_CARE);
+    hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/polygon-smooth"));
+    stateSet->setAttribute(hint);
+    hint = new osg::Hint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
+    hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/line-smooth"));
+    stateSet->setAttribute(hint);
+    hint = new osg::Hint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
+    hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/point-smooth"));
+    stateSet->setAttribute(hint);
+    hint = new osg::Hint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
+    hint->setUpdateCallback(new FGHintUpdateCallback("/sim/rendering/perspective-correction"));
+    stateSet->setAttribute(hint);
 
     osg::Group* sceneGroup = new osg::Group;
     sceneGroup->addChild(globals->get_scenery()->get_scene_graph());
-    sceneGroup->addChild(thesky->getCloudRoot());
+    sceneGroup->setNodeMask(~simgear::BACKGROUND_BIT);
+
+    //sceneGroup->addChild(thesky->getCloudRoot());
 
     stateSet = sceneGroup->getOrCreateStateSet();
-    stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
     stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
 
     // need to update the light on every frame
@@ -501,14 +480,12 @@ FGRenderer::init( void ) {
     // relative because of CameraView being just a clever transform node
     lightSource->setReferenceFrame(osg::LightSource::RELATIVE_RF);
     lightSource->setLocalStateSetModes(osg::StateAttribute::ON);
-    mRoot->addChild(lightSource);
-
-    lightSource->addChild(mBackGroundCamera.get());
+    
     lightSource->addChild(sceneGroup);
-
+    lightSource->addChild(thesky->getPreRoot());
+    mRoot->addChild(lightSource);
 
     stateSet = globals->get_scenery()->get_scene_graph()->getOrCreateStateSet();
-    stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
     stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
     stateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
     stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
@@ -531,30 +508,21 @@ FGRenderer::init( void ) {
     stateSet->setUpdateCallback(new FGFogEnableUpdateCallback);
 
     // plug in the GUI
-    osg::Camera* guiCamera = new osg::Camera;
-    guiCamera->setRenderOrder(osg::Camera::POST_RENDER, 100);
-    guiCamera->setClearMask(0);
-    inheritanceMask = osg::CullSettings::ALL_VARIABLES;
-    inheritanceMask &= ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE;
-    inheritanceMask &= ~osg::CullSettings::CULLING_MODE;
-    guiCamera->setInheritanceMask(inheritanceMask);
-    guiCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-    guiCamera->setCullingMode(osg::CullSettings::NO_CULLING);
-    osg::Geode* geode = new osg::Geode;
-    geode->addDrawable(new SGPuDrawable);
-    geode->addDrawable(new SGHUDAndPanelDrawable);
-    guiCamera->addChild(geode);
-
-    mCameraView->addChild(mRoot.get());
-
+    osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
+    if (guiCamera) {
+        osg::Geode* geode = new osg::Geode;
+        geode->addDrawable(new SGPuDrawable);
+        geode->addDrawable(new SGHUDAndPanelDrawable);
+        guiCamera->addChild(geode);
+    }
     osg::Switch* sw = new osg::Switch;
     sw->setUpdateCallback(new FGScenerySwitchCallback);
-    sw->addChild(mCameraView.get());
+    sw->addChild(mRoot.get());
+    viewPartition->addChild(sw);
+    viewPartition->addChild(thesky->getCloudRoot());
 
-    mRealRoot->addChild(sw);
+    mRealRoot->addChild(viewPartition.get());
     mRealRoot->addChild(FGCreateRedoutNode());
-    mRealRoot->addChild(guiCamera);
-//  sceneView->getState()->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
 }
 
 
@@ -568,14 +536,8 @@ FGRenderer::update( bool refresh_camera_settings ) {
         fgSetDouble("/sim/startup/splash-alpha", 1.0);
 
         // Keep resetting sim time while the sim is initializing
-        globals->set_sim_time_sec( 0.0 );
-
         // the splash screen is now in the scenegraph
-       if (!viewer) {
-           sceneView->update();
-           sceneView->cull();
-           sceneView->draw();
-       }
+        globals->set_sim_time_sec( 0.0 );
         return;
     }
 
@@ -617,25 +579,9 @@ FGRenderer::update( bool refresh_camera_settings ) {
         // update view port
         resize( fgGetInt("/sim/startup/xsize"),
                 fgGetInt("/sim/startup/ysize") );
-
-        SGVec3d position = current__view->getViewPosition();
-        SGQuatd attitude = current__view->getViewOrientation();
-        SGVec3d osgPosition = attitude.transform(-position);
-       if (viewer) {
-           FGManipulator *manipulator
-               = globals->get_renderer()->getManipulator();
-           manipulator->setPosition(position.osg());
-           manipulator->setAttitude(attitude.osg());
-       } else {
-           mCameraView->setPosition(osgPosition.osg());
-           mCameraView->setAttitude(inverse(attitude).osg());
-       }
     }
-    osg::Camera *camera;
-    if (viewer)
-       camera = viewer->getCamera();
-    else
-       camera = sceneView->getCamera();
+    osg::Camera *camera = viewer->getCamera();
+
     if ( skyblend ) {
        
         if ( fgGetBool("/sim/rendering/textures") ) {
@@ -756,23 +702,6 @@ FGRenderer::update( bool refresh_camera_settings ) {
     }
 
 //     sgEnviro.setLight(l->adj_fog_color());
-
-    // texture parameters
-    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
-
-    double agl = current__view->getAltitudeASL_ft()*SG_FEET_TO_METER
-      - current__view->getSGLocation()->get_cur_elev_m();
-
-    float scene_nearplane, scene_farplane;
-    if ( agl > 10.0 ) {
-        scene_nearplane = 10.0f;
-        scene_farplane = 120000.0f;
-    } else {
-        scene_nearplane = groundlevel_nearplane->getDoubleValue();
-        scene_farplane = 120000.0f;
-    }
-    setNearFar( scene_nearplane, scene_farplane );
-
 //     sgEnviro.startOfFrame(current__view->get_view_pos(), 
 //         current__view->get_world_up(),
 //         current__view->getLongitude_deg(),
@@ -787,27 +716,12 @@ FGRenderer::update( bool refresh_camera_settings ) {
 //         fgGetDouble("/velocities/airspeed-kt", 0.0)
 //                        * cos( fgGetDouble("/orientation/pitch-deg", 0.0)
 //                                * SGD_DEGREES_TO_RADIANS);
-       // TODO:find the real view speed, not the AC one
-//     sgEnviro.drawPrecipitation(
-//         fgGetDouble("/environment/metar/rain-norm", 0.0),
-//         fgGetDouble("/environment/metar/snow-norm", 0.0),
-//         fgGetDouble("/environment/metar/hail-norm", 0.0),
-//         current__view->getPitch_deg() + current__view->getPitchOffset_deg(),
-//         current__view->getRoll_deg() + current__view->getRollOffset_deg(),
-//         - current__view->getHeadingOffset_deg(),
-//                current_view_origin_airspeed_horiz_kt
-//                );
 
     // OSGFIXME
 //     if( is_internal )
 //         shadows->endOfFrame();
 
     // need to call the update visitor once
-    if (!viewer) {
-       mFrameStamp->setReferenceTime(globals->get_sim_time_sec());
-        mFrameStamp->setSimulationTime(globals->get_sim_time_sec());
-       mFrameStamp->setFrameNumber(1+mFrameStamp->getFrameNumber());
-    }
     mFrameStamp->setCalendarTime(*globals->get_time_params()->getGmt());
     mUpdateVisitor->setViewData(current__view->getViewPosition(),
                                 current__view->getViewOrientation());
@@ -817,24 +731,18 @@ FGRenderer::update( bool refresh_camera_settings ) {
                              l->adj_fog_color(),
                              l->get_sun_angle()*SGD_RADIANS_TO_DEGREES);
     mUpdateVisitor->setVisibility(actual_visibility);
+    viewPartition->setVisibility(actual_visibility);
+    simgear::GroundLightManager::instance()->update(mUpdateVisitor.get());
     bool hotspots = fgGetBool("/sim/panel-hotspots");
-    if (viewer) {
-       if (hotspots)
-           camera->setCullMask(camera->getCullMask()|SG_NODEMASK_PICK_BIT);
-       else
-           camera->setCullMask(camera->getCullMask()
-                               & ~SG_NODEMASK_PICK_BIT);
-    } else {
-       if (hotspots)
-           sceneView->setCullMask(sceneView->getCullMask()
-                                  |SG_NODEMASK_PICK_BIT);
-       else
-           sceneView->setCullMask(sceneView->getCullMask()
-                                  &(~SG_NODEMASK_PICK_BIT));
-       sceneView->update();
-       sceneView->cull();
-       sceneView->draw();
-    }
+    osg::Node::NodeMask cullMask = ~simgear::LIGHTS_BITS & ~simgear::PICK_BIT;
+    cullMask |= simgear::GroundLightManager::instance()
+        ->getLightNodeMask(mUpdateVisitor.get());
+    if (hotspots)
+        cullMask |= simgear::PICK_BIT;
+    camera->setCullMask(cullMask);
+    // XXX
+    for (int i = 0; i < viewer->getNumSlaves(); ++i)
+        viewer->getSlave(i)._camera->setCullMask(cullMask);
 }
 
 
@@ -852,14 +760,6 @@ FGRenderer::resize( int width, int height ) {
     } else {
         view_h = height;
     }
-    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
-    if (viewer)
-        ;
-  //       viewer->getCamera()->getViewport()->setViewport(0, height - view_h,
-//                                                         width, view_h);
-    else
-       sceneView->getViewport()->setViewport(0, height - view_h,
-                                             width, view_h);
 
     static int lastwidth = 0;
     static int lastheight = 0;
@@ -868,8 +768,6 @@ FGRenderer::resize( int width, int height ) {
     if (height != lastheight)
         fgSetInt("/sim/startup/ysize", lastheight = height);
 
-    guiInitMouse(width, height);
-
     // for all views
     FGViewMgr *viewmgr = globals->get_viewmgr();
     if (viewmgr) {
@@ -877,175 +775,54 @@ FGRenderer::resize( int width, int height ) {
         viewmgr->get_view(i)->
           set_aspect_ratio((float)view_h / (float)width);
       }
-
-      setFOV( viewmgr->get_current_view()->get_h_fov(),
-              viewmgr->get_current_view()->get_v_fov() );
     }
 }
 
-
-// we need some static storage space for these values.  However, we
-// can't store it in a renderer class object because the functions
-// that manipulate these are static.  They are static so they can
-// interface to the display callback system.  There's probably a
-// better way, there has to be a better way, but I'm not seeing it
-// right now.
-static float fov_width = 55.0;
-static float fov_height = 42.0;
-static float fov_near = 1.0;
-static float fov_far = 1000.0;
-
-
-/** FlightGear code should use this routine to set the FOV rather than
- *  calling the ssg routine directly
- */
-void FGRenderer::setFOV( float w, float h ) {
-    fov_width = w;
-    fov_height = h;
-    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
-    if (viewer)
-       viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
-    else
-       sceneView->setProjectionMatrixAsPerspective(fov_height,
-                                                   fov_width/fov_height,
-                                                   fov_near, fov_far);
-}
-
-
-/** FlightGear code should use this routine to set the Near/Far clip
- *  planes rather than calling the ssg routine directly
- */
-void FGRenderer::setNearFar( float n, float f ) {
-// OSGFIXME: we have currently too much z-buffer fights
-n = 0.1;
-    fov_near = n;
-    fov_far = f;
+void FGRenderer::setCameraParameters(float vfov, float aspectRatio,
+                                     float zNear, float zFar)
+{
+    zNear = .1;
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
-    if (viewer)
-       viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, fov_near, fov_far);
-    else
-       sceneView->setProjectionMatrixAsPerspective(fov_height,
-                                                   fov_width/fov_height,
-                                                   fov_near, fov_far);
-
+    viewer->getCamera()->setProjectionMatrixAsPerspective(vfov,
+                                                          1.0f / aspectRatio,
+                                                          zNear, zFar);
+    
 }
-
 bool
-FGRenderer::pick( unsigned x, unsigned y,
-                  std::vector<SGSceneryPick>& pickList,
-                  const osgGA::GUIEventAdapter* ea )
+FGRenderer::pick(std::vector<SGSceneryPick>& pickList,
+                 const osgGA::GUIEventAdapter* ea)
 {
-  osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
-  // wipe out the return ...
-  pickList.resize(0);
-
-  if (sceneView.valid()) {
-    osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
-    if (!sceneData)
-      return false;
-
-    osg::Viewport* viewport = sceneView->getViewport();
-    if (!viewport)
-      return false;
-    // don't know why, but the update has partly happened somehow,
-    // so update the scenery part of the viewer
-    FGViewer *current_view = globals->get_current_view();
-    // Force update of center dependent values ...
-    current_view->set_dirty();
-    SGVec3d position = current_view->getViewPosition();
-    SGQuatd attitude = current_view->getViewOrientation();
-    SGVec3d osgPosition = attitude.transform(-position);
-    mCameraView->setPosition(osgPosition.osg());
-    mCameraView->setAttitude(inverse(attitude).osg());
-
-    osg::Matrix projection(sceneView->getProjectionMatrix());
-    osg::Matrix modelview(sceneView->getViewMatrix());
-
-    osg::NodePathList nodePath = sceneData->getParentalNodePaths();
-    // modify the view matrix so that it accounts for this nodePath's
-    // accumulated transform
-    if (!nodePath.empty())
-      modelview.preMult(computeLocalToWorld(nodePath.front()));
-
-    // swap the y values ...
-    y = viewport->height() - y;
-    // set up the pick visitor
-    osgUtil::PickVisitor pickVisitor(viewport, projection, modelview, x, y);
-    sceneData->accept(pickVisitor);
-    if (!pickVisitor.hits())
-      return false;
-    
-    // collect all interaction callbacks on the pick ray.
-    // They get stored in the pickCallbacks list where they are sorted back
-    // to front and croasest to finest wrt the scenery node they are attached to
-    osgUtil::PickVisitor::LineSegmentHitListMap::const_iterator mi;
-    for (mi = pickVisitor.getSegHitList().begin();
-         mi != pickVisitor.getSegHitList().end();
-         ++mi) {
-      osgUtil::IntersectVisitor::HitList::const_iterator hi;
-      for (hi = mi->second.begin(); hi != mi->second.end(); ++hi) {
-        // ok, go back the nodes and ask for intersection callbacks,
-        // execute them in top down order
-        const osg::NodePath& np = hi->getNodePath();
-        osg::NodePath::const_reverse_iterator npi;
-        for (npi = np.rbegin(); npi != np.rend(); ++npi) {
-          SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
-          if (!ud)
-            continue;
-          for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
-            SGPickCallback* pickCallback = ud->getPickCallback(i);
-            if (!pickCallback)
-              continue;
-            SGSceneryPick sceneryPick;
-            /// note that this is done totally in doubles instead of
-            /// just using getWorldIntersectionPoint
-            osg::Vec3d localPt = hi->getLocalIntersectPoint();
-            sceneryPick.info.local = SGVec3d(localPt);
-            if (hi->getMatrix())
-              sceneryPick.info.wgs84 = SGVec3d(localPt*(*hi->getMatrix()));
-            else
-              sceneryPick.info.wgs84 = SGVec3d(localPt);
-            sceneryPick.callback = pickCallback;
-            pickList.push_back(sceneryPick);
-          }
-        }
-      }
-    }
-    
-    return !pickList.empty();
-
-  } else if (viewer) {
-
-    // just compute intersections in the viewers method ...
+    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+    // wipe out the return ...
+    pickList.clear();
     typedef osgUtil::LineSegmentIntersector::Intersections Intersections;
     Intersections intersections;
-    viewer->computeIntersections(ea->getX(), ea->getY(), intersections);
-
-    Intersections::iterator hit;
-    for (hit = intersections.begin(); hit != intersections.end(); ++hit) {
-      const osg::NodePath& np = hit->nodePath;
-      osg::NodePath::const_reverse_iterator npi;
-      for (npi = np.rbegin(); npi != np.rend(); ++npi) {
-        SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
-        if (!ud)
-          continue;
-        for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
-          SGPickCallback* pickCallback = ud->getPickCallback(i);
-          if (!pickCallback)
-            continue;
-          SGSceneryPick sceneryPick;
-          sceneryPick.info.local = SGVec3d(hit->getLocalIntersectPoint());
-          sceneryPick.info.wgs84 = SGVec3d(hit->getWorldIntersectPoint());
-          sceneryPick.callback = pickCallback;
-          pickList.push_back(sceneryPick);
+
+    if (!computeIntersections(CameraGroup::getDefault(), ea, intersections))
+        return false;
+    for (Intersections::iterator hit = intersections.begin(),
+             e = intersections.end();
+         hit != e;
+         ++hit) {
+        const osg::NodePath& np = hit->nodePath;
+        osg::NodePath::const_reverse_iterator npi;
+        for (npi = np.rbegin(); npi != np.rend(); ++npi) {
+            SGSceneUserData* ud = SGSceneUserData::getSceneUserData(*npi);
+            if (!ud)
+                continue;
+            for (unsigned i = 0; i < ud->getNumPickCallbacks(); ++i) {
+                SGPickCallback* pickCallback = ud->getPickCallback(i);
+                if (!pickCallback)
+                    continue;
+                SGSceneryPick sceneryPick;
+                sceneryPick.info.local = SGVec3d(hit->getLocalIntersectPoint());
+                sceneryPick.info.wgs84 = SGVec3d(hit->getWorldIntersectPoint());
+                sceneryPick.callback = pickCallback;
+                pickList.push_back(sceneryPick);
+            }
         }
-      }
     }
-
     return !pickList.empty();
-  } else {                     // we can get called early ...
-    return false;
-  }
 }
 
 void
@@ -1060,5 +837,18 @@ fgDumpSceneGraphToFile(const char* filename)
     return osgDB::writeNodeFile(*mRealRoot.get(), filename);
 }
 
+bool
+fgDumpTerrainBranchToFile(const char* filename)
+{
+    return osgDB::writeNodeFile( *globals->get_scenery()->get_terrain_branch(),
+                                 filename );
+}
+
+// For debugging
+bool
+fgDumpNodeToFile(osg::Node* node, const char* filename)
+{
+    return osgDB::writeNodeFile(*node, filename);
+}
 // end of renderer.cxx