]> git.mxchange.org Git - flightgear.git/commitdiff
Modified Files:
authorfrohlich <frohlich>
Sat, 26 May 2007 13:53:46 +0000 (13:53 +0000)
committerfrohlich <frohlich>
Sat, 26 May 2007 13:53:46 +0000 (13:53 +0000)
  src/Input/input.cxx src/Input/input.hxx
src/Main/FGManipulator.cxx src/Main/fg_os.cxx
  src/Main/fg_os.hxx src/Main/fg_os_osgviewer.cxx
src/Main/fg_os_sdl.cxx src/Main/renderer.cxx
src/Main/renderer.hxx: First cut of osg multi view configurations.

src/Input/input.cxx
src/Input/input.hxx
src/Main/FGManipulator.cxx
src/Main/fg_os.cxx
src/Main/fg_os.hxx
src/Main/fg_os_osgviewer.cxx
src/Main/fg_os_sdl.cxx
src/Main/renderer.cxx
src/Main/renderer.hxx

index 98fe85bcd9c63bf50271fabd58170533075076e3..fdb13de5e5e828b81051838bd9bfdaf2bed09e9a 100644 (file)
@@ -66,7 +66,7 @@ SG_USING_STD(ifstream);
 SG_USING_STD(string);
 SG_USING_STD(vector);
 
-void mouseClickHandler(int button, int updown, int x, int y);
+void mouseClickHandler(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
 void mouseMotionHandler(int x, int y);
 void keyHandler(int key, int keymod, int mousex, int mousey);
 
@@ -247,7 +247,7 @@ FGInput::doKey (int k, int modifiers, int x, int y)
 }
 
 void
-FGInput::doMouseClick (int b, int updown, int x, int y)
+FGInput::doMouseClick (int b, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter* ea)
 {
   int modifiers = fgGetKeyModifiers();
 
@@ -272,13 +272,15 @@ FGInput::doMouseClick (int b, int updown, int x, int y)
   }
 
   if (mode.pass_through) {
-    if (puMouse(b, updown, x, y))
+    // The pu stuff seems to need that. May be it does opengl picking ...
+    fgMakeCurrent();
+    if (0 <= x && 0 <= y && puMouse(b, updown, x, y))
       return;
-    else if ((globals->get_current_panel() != 0) &&
+    else if (0 <= x && 0 <= y && (globals->get_current_panel() != 0) &&
              globals->get_current_panel()->getVisibility() &&
              globals->get_current_panel()->doMouseAction(b, updown, x, y))
       return;
-    else if (fgHandle3DPanelMouseEvent(b, updown, x, y))
+    else if (0 <= x && 0 <= y && fgHandle3DPanelMouseEvent(b, updown, x, y))
       return;
     else {
       // pui didn't want the click event so compute a
@@ -291,7 +293,7 @@ FGInput::doMouseClick (int b, int updown, int x, int y)
         // The nearest one is the first one and the deepest
         // (the most specialized one in the scenegraph) is the first.
         std::vector<SGSceneryPick> pickList;
-        if (FGRenderer::pick(x, y, pickList)) {
+        if (FGRenderer::pick(x, y, pickList, ea)) {
           std::vector<SGSceneryPick>::const_iterator i;
           for (i = pickList.begin(); i != pickList.end(); ++i) {
             if (i->callback->buttonPressed(b, i->info)) {
@@ -1097,10 +1099,10 @@ void keyHandler(int key, int keymod, int mousex, int mousey)
         default_input->doKey(key, keymod, mousex, mousey);
 }
 
-void mouseClickHandler(int button, int updown, int x, int y)
+void mouseClickHandler(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter* ea)
 {
     if(default_input)
-        default_input->doMouseClick(button, updown, x, y);
+      default_input->doMouseClick(button, updown, x, y, mainWindow, ea);
 }
 
 void mouseMotionHandler(int x, int y)
index 7a981b0fac2bcd2b00c5b8547a193136c373c078..99116dbe648200d6a9c7cd0cb1505343ada88d1a 100644 (file)
@@ -134,7 +134,7 @@ public:
    * @param x The X position of the mouse event, in screen coordinates.
    * @param y The Y position of the mouse event, in screen coordinates.
    */
-  virtual void doMouseClick (int button, int updown, int x, int y);
+  virtual void doMouseClick (int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
 
 
   /**
index a5078fb59cad1f8773586c451a0c7da2ac5b28fe..580b82d486a048879e8c7ec6988fa8a0594af36c 100644 (file)
@@ -44,9 +44,8 @@ osg::Node* FGManipulator::getNode()
     return _node.get();
 }
 
-namespace {
 // All the usual translation from window system to FG / plib
-int osgToFGModifiers(int modifiers)
+static int osgToFGModifiers(int modifiers)
 {
     int result = 0;
     if (modifiers & (osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT |
@@ -60,7 +59,6 @@ int osgToFGModifiers(int modifiers)
        result |= KEYMOD_ALT;
     return result;
 }
-} // namespace
 
 void FGManipulator::init(const osgGA::GUIEventAdapter& ea,
                         osgGA::GUIActionAdapter& us)
@@ -69,17 +67,29 @@ void FGManipulator::init(const osgGA::GUIEventAdapter& ea,
     (void)handle(ea, us);
 }
 
-namespace {
-void eventToViewport(const osgGA::GUIEventAdapter& ea,
-                    osgGA::GUIActionAdapter& us,
-                    int& x, int& y)
+static bool
+eventToViewport(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us,
+                int& x, int& y)
 {
-    x = (int)ea.getX();
-    y = (int)ea.getY();
-    if (ea.getMouseYOrientation()
-       == osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
-       y = (int)ea.getWindowHeight() - y;
-}
+  x = -1;
+  y = -1;
+
+  const osgViewer::Viewer* viewer;
+  viewer = dynamic_cast<const osgViewer::Viewer*>(&us);
+  if (!viewer)
+      return false;
+
+  float lx, ly;
+  const osg::Camera* camera;
+  camera = viewer->getCameraContainingPosition(ea.getX(), ea.getY(), lx, ly);
+
+  if (!fgOSIsMainCamera(camera))
+      return false;
+
+  x = int(lx);
+  y = int(camera->getViewport()->height() - ly);
+
+  return true;
 }
 
 bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
@@ -101,12 +111,12 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
        eventToViewport(ea, us, x, y);
        if (keyHandler)
            (*keyHandler)(key, modmask, x, y);
+        return true;
     }
-    return true;
     case osgGA::GUIEventAdapter::PUSH:
     case osgGA::GUIEventAdapter::RELEASE:
     {
-       eventToViewport(ea, us, x, y);
+        bool mainWindow = eventToViewport(ea, us, x, y);
        int button = 0;
        switch (ea.getButton()) {
        case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
@@ -122,7 +132,7 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
        if (mouseClickHandler)
            (*mouseClickHandler)(button,
                                 (ea.getEventType()
-                                 == osgGA::GUIEventAdapter::RELEASE), x, y);
+                                 == osgGA::GUIEventAdapter::RELEASE), x, y, mainWindow, &ea);
        return true;
     }
     case osgGA::GUIEventAdapter::MOVE:
@@ -131,10 +141,6 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
        if (mouseMotionHandler)
            (*mouseMotionHandler)(x, y);
        return true;
-    case osgGA::GUIEventAdapter::RESIZE:
-       if (windowResizeHandler)
-           (*windowResizeHandler)(ea.getWindowWidth(), ea.getWindowHeight());
-       return true;
     case osgGA::GUIEventAdapter::CLOSE_WINDOW:
     case osgGA::GUIEventAdapter::QUIT_APPLICATION:
         fgOSExit(0);
@@ -143,7 +149,7 @@ bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
        return false;
     }
 }
-           
+
 void FGManipulator::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
                              int& modifiers)
 {
index 26767fcc4554dcab108d0397650ee548a8a95259..a9fcf86c9ad358e5188fc6c2a40bc66f922b0eff 100644 (file)
@@ -90,7 +90,7 @@ static void GLUTmotion (int x, int y)
 static void GLUTmouse (int button, int updown, int x, int y)
 {
     GlutModifiers = glutGetModifiers();
-    if(MouseClickHandler) (*MouseClickHandler)(button, updown, x, y);
+    if(MouseClickHandler) (*MouseClickHandler)(button, updown, x, y, true, 0);
 }
 
 static void GLUTspecialkeyup(int k, int x, int y)
@@ -240,3 +240,13 @@ void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
 void fgMakeCurrent()
 {
 }
+
+bool fgOSIsMainCamera(const osg::Camera*)
+{
+  return true;
+}
+
+bool fgOSIsMainContext(const osg::GraphicsContext*)
+{
+  return true;
+}
index 931dcb10fedf1780dd30ace7699ce29dd53f7412..9bbbb4d95ebed17be798ccc1b893773e7fd8bc34 100644 (file)
@@ -60,12 +60,15 @@ void fgRequestRedraw();
 // Callbacks and registration API
 //
 
+namespace osg { class Camera; class GraphicsContext; }
+namespace osgGA { class GUIEventAdapter; }
+
 typedef void (*fgIdleHandler)();
 typedef void (*fgDrawHandler)();
 typedef void (*fgWindowResizeHandler)(int w, int h);
 
 typedef void (*fgKeyHandler)(int key, int keymod, int mousex, int mousey);
-typedef void (*fgMouseClickHandler)(int button, int updown, int x, int y);
+typedef void (*fgMouseClickHandler)(int button, int updown, int x, int y, bool mainWindow, const osgGA::GUIEventAdapter*);
 typedef void (*fgMouseMotionHandler)(int x, int y);
 
 void fgRegisterIdleHandler(fgIdleHandler func);
@@ -77,4 +80,8 @@ void fgRegisterMouseClickHandler(fgMouseClickHandler func);
 void fgRegisterMouseMotionHandler(fgMouseMotionHandler func);
 
 void fgMakeCurrent();
+
+bool fgOSIsMainCamera(const osg::Camera* camera);
+bool fgOSIsMainContext(const osg::GraphicsContext* context);
+
 #endif // _FG_OS_HXX
index 12064723789fa38aa0963c2f4908cc655babd6a2..7cde2a83d01473697d5f81c5f4a02a08c35899cb 100644 (file)
@@ -13,6 +13,7 @@
 #include <osgGA/MatrixManipulator>
 
 #include "fg_os.hxx"
+#include "fg_props.hxx"
 #include "util.hxx"
 #include "globals.hxx"
 #include "renderer.hxx"
@@ -65,42 +66,133 @@ void fgRequestRedraw()
 // fg_os implementation
 //
 
-
 static osg::ref_ptr<osgViewer::Viewer> viewer;
+static osg::ref_ptr<osg::Camera> mainCamera;
 
 void fgOSOpenWindow(int w, int h, int bpp,
                     bool alpha, bool stencil, bool fullscreen)
 {
+    osg::GraphicsContext::WindowingSystemInterface* wsi;
+    wsi = osg::GraphicsContext::getWindowingSystemInterface();
+
     viewer = new osgViewer::Viewer;
     // Avoid complications with fg's custom drawables.
-    viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
-    osg::ref_ptr<osg::GraphicsContext::Traits> traits
-       = new osg::GraphicsContext::Traits;
+    std::string mode;
+    mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded");
+    if (mode == "AutomaticSelection")
+      viewer->setThreadingModel(osgViewer::Viewer::AutomaticSelection);
+    else if (mode == "CullDrawThreadPerContext")
+      viewer->setThreadingModel(osgViewer::Viewer::CullDrawThreadPerContext);
+    else if (mode == "DrawThreadPerContext")
+      viewer->setThreadingModel(osgViewer::Viewer::DrawThreadPerContext);
+    else if (mode == "CullThreadPerCameraDrawThreadPerContext")
+      viewer->setThreadingModel(osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext);
+    else
+      viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
+    osg::ref_ptr<osg::GraphicsContext::Traits> traits;
+    traits = new osg::GraphicsContext::Traits;
     int cbits = (bpp <= 16) ?  5 :  8;
     int zbits = (bpp <= 16) ? 16 : 24;
-    traits->width = w;
-    traits->height = h;
     traits->red = traits->green = traits->blue = cbits;
     traits->depth = zbits;
     if (alpha)
        traits->alpha = 8;
     if (stencil)
        traits->stencil = 8;
-    if (fullscreen)
+    traits->doubleBuffer = true;
+    traits->mipMapGeneration = true;
+    traits->windowName = "FlightGear";
+    traits->sampleBuffers = fgGetBool("/sim/rendering/multi-sample-buffers", traits->sampleBuffers);
+    traits->samples = fgGetBool("/sim/rendering/multi-samples", traits->samples);
+    traits->vsync = fgGetBool("/sim/rendering/vsync-enable", traits->vsync);
+
+    if (fullscreen) {
+        unsigned width = 0;
+        unsigned height = 0;
+        wsi->getScreenResolution(*traits, width, height);
        traits->windowDecoration = false;
-    else
+        traits->width = width;
+        traits->height = height;
+        traits->supportsResize = false;
+    } else {
        traits->windowDecoration = true;
-    traits->supportsResize = true;
-    traits->doubleBuffer = true;
-    osg::GraphicsContext* gc
-       = osg::GraphicsContext::createGraphicsContext(traits.get());
-    viewer->getCamera()->setGraphicsContext(gc);
+        traits->width = w;
+        traits->height = h;
+        traits->supportsResize = true;
+    }
+
+    osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
+
+    // Ok, first the children.
+    // that achieves some magic ordering og the slaves so that we end up
+    // in the main window more often.
+    // This can be sorted out better when we got rid of glut and sdl.
+    if (fgHasNode("/sim/rendering/camera")) {
+      SGPropertyNode* renderingNode = fgGetNode("/sim/rendering");
+      for (int i = 0; i < renderingNode->nChildren(); ++i) {
+        SGPropertyNode* cameraNode = renderingNode->getChild(i);
+        if (strcmp(cameraNode->getName(), "camera") != 0)
+          continue;
+
+        // get a new copy of the traits struct
+        osg::ref_ptr<osg::GraphicsContext::Traits> cameraTraits;
+        cameraTraits = new osg::GraphicsContext::Traits(*traits);
+
+        double shearx = cameraNode->getDoubleValue("shear-x", 0);
+        double sheary = cameraNode->getDoubleValue("shear-y", 0);
+        cameraTraits->hostName = cameraNode->getStringValue("host-name", "");
+        cameraTraits->displayNum = cameraNode->getIntValue("display", 0);
+        cameraTraits->screenNum = cameraNode->getIntValue("screen", 0);
+        if (cameraNode->getBoolValue("fullscreen", fullscreen)) {
+          unsigned width = 0;
+          unsigned height = 0;
+          wsi->getScreenResolution(*cameraTraits, width, height);
+          cameraTraits->windowDecoration = false;
+          cameraTraits->width = width;
+          cameraTraits->height = height;
+          cameraTraits->supportsResize = false;
+        } else {
+          cameraTraits->windowDecoration = true;
+          cameraTraits->width = cameraNode->getIntValue("width", w);
+          cameraTraits->height = cameraNode->getIntValue("height", h);
+          cameraTraits->supportsResize = true;
+        }
+        // FIXME, currently this is too much of a problem to route the resize
+        // events. When we do no longer need sdl and such this
+        // can be simplified
+        cameraTraits->supportsResize = false;
+
+        // ok found a camera configuration, add a new slave ...
+        osg::ref_ptr<osg::Camera> camera = new osg::Camera;
+
+        osg::GraphicsContext* gc;
+        gc = osg::GraphicsContext::createGraphicsContext(cameraTraits.get());
+        gc->realize();
+        camera->setGraphicsContext(gc);
+        // If a viewport isn't set on the camera, then it's hard to dig it
+        // out of the SceneView objects in the viewer, and the coordinates
+        // of mouse events are somewhat bizzare.
+        camera->setViewport(new osg::Viewport(0, 0, cameraTraits->width, cameraTraits->height));
+        camera->setProjectionResizePolicy(rsp);
+        viewer->addSlave(camera.get(), osg::Matrix::translate(-shearx, -sheary, 0), osg::Matrix());
+      }
+    }
+
+    // now the main camera ...
+    osg::ref_ptr<osg::Camera> camera = new osg::Camera;
+    mainCamera = camera;
+    osg::GraphicsContext* gc;
+    gc = osg::GraphicsContext::createGraphicsContext(traits.get());
+    gc->realize();
+    gc->makeCurrent();
+    camera->setGraphicsContext(gc);
     // If a viewport isn't set on the camera, then it's hard to dig it
     // out of the SceneView objects in the viewer, and the coordinates
     // of mouse events are somewhat bizzare.
-    viewer->getCamera()->setViewport(new osg::Viewport(0, 0,
-                                                      traits->width,
-                                                      traits->height));
+    camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
+    camera->setProjectionResizePolicy(rsp);
+    viewer->addSlave(camera.get());
+
     viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
     // Let FG handle the escape key with a confirmation
     viewer->setKeyEventSetsDone(0);
@@ -134,7 +226,8 @@ int fgGetKeyModifiers()
 
 void fgWarpMouse(int x, int y)
 {
-    viewer->requestWarpPointer((float)x, (float)y);
+  // Hack, currently the pointer is just recentered. So, we know the relative coordinates ...
+    viewer->requestWarpPointer(0, 0);
 }
 
 // Noop
@@ -142,24 +235,85 @@ void fgOSInit(int* argc, char** argv)
 {
 }
 
+// Noop
 void fgOSFullScreen()
 {
-    // Noop, but is probably doable
+}
 
+// #define OSG_HAS_MOUSE_CURSOR_PATCH
+#ifdef OSG_HAS_MOUSE_CURSOR_PATCH
+static void setMouseCursor(osg::Camera* camera, int cursor)
+{
+    if (!camera)
+        return;
+    osg::GraphicsContext* gc = camera->getGraphicsContext();
+    if (!gc)
+        return;
+    osgViewer::GraphicsWindow* gw;
+    gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc);
+    if (!gw)
+        return;
+    
+    osgViewer::GraphicsWindow::MouseCursor mouseCursor;
+    mouseCursor = osgViewer::GraphicsWindow::InheritCursor;
+    if     (cursor == MOUSE_CURSOR_NONE)
+        mouseCursor = osgViewer::GraphicsWindow::NoCursor;
+    else if(cursor == MOUSE_CURSOR_POINTER)
+        mouseCursor = osgViewer::GraphicsWindow::RightArrowCursor;
+    else if(cursor == MOUSE_CURSOR_WAIT)
+        mouseCursor = osgViewer::GraphicsWindow::WaitCursor;
+    else if(cursor == MOUSE_CURSOR_CROSSHAIR)
+        mouseCursor = osgViewer::GraphicsWindow::CrosshairCursor;
+    else if(cursor == MOUSE_CURSOR_LEFTRIGHT)
+        mouseCursor = osgViewer::GraphicsWindow::LeftRightCursor;
+
+    gw->setCursor(mouseCursor);
 }
+#endif
+
+static int _cursor = -1;
 
-// No support in OSG yet
 void fgSetMouseCursor(int cursor)
 {
+    _cursor = cursor;
+#ifdef OSG_HAS_MOUSE_CURSOR_PATCH
+    setMouseCursor(viewer->getCamera(), cursor);
+    for (unsigned i = 0; i < viewer->getNumSlaves(); ++i)
+        setMouseCursor(viewer->getSlave(i)._camera.get(), cursor);
+#endif
 }
 
 int fgGetMouseCursor()
 {
-    return 0;
+    return _cursor;
 }
 
 void fgMakeCurrent()
 {
-    osg::GraphicsContext* gc = viewer->getCamera()->getGraphicsContext();
+    if (!mainCamera.valid())
+        return;
+    osg::GraphicsContext* gc = mainCamera->getGraphicsContext();
+    if (!gc)
+        return;
     gc->makeCurrent();
 }
+
+bool fgOSIsMainContext(const osg::GraphicsContext* context)
+{
+    if (!mainCamera.valid())
+        return false;
+    return context == mainCamera->getGraphicsContext();
+}
+
+bool fgOSIsMainCamera(const osg::Camera* camera)
+{
+  if (!camera)
+    return false;
+  if (camera == mainCamera.get())
+    return true;
+  if (!viewer.valid())
+    return false;
+  if (camera == viewer->getCamera())
+    return true;
+  return false;
+}
index e9ad6f7759094b649990598405eb43fd1fb2ae99..7917832075409f7473ffa640c15a00a1ac243957 100644 (file)
@@ -226,7 +226,7 @@ void fgOSMainLoop()
                 if(MouseClickHandler)
                     (*MouseClickHandler)(e.button.button - 1,
                                          e.button.state == SDL_RELEASED,
-                                         e.button.x, e.button.y);
+                                         e.button.x, e.button.y, true, 0);
                 break;
             case SDL_MOUSEMOTION:
                 CurrentMouseX = e.motion.x;
@@ -412,3 +412,13 @@ static void initCursors()
 void fgMakeCurrent()
 {
 }
+
+bool fgOSIsMainCamera(const osg::Camera*)
+{
+  return true;
+}
+
+bool fgOSIsMainContext(const osg::GraphicsContext*)
+{
+  return true;
+}
index a6ab199bb39f38eee8b74b0f46ee536e89edab9c..b4dcbc9e7771642e10e35a73ad074f3248c25b30 100644 (file)
@@ -54,6 +54,7 @@
 #include <osgUtil/SceneView>
 #include <osgUtil/UpdateVisitor>
 #include <osgUtil/IntersectVisitor>
+#include <osgUtil/LineSegmentIntersector>
 
 #include <osg/io_utils>
 #include <osgDB/WriteFile>
@@ -125,6 +126,9 @@ public:
   { drawImplementation(*renderInfo.getState()); }
   void drawImplementation(osg::State& state) const
   {
+    if (!fgOSIsMainContext(state.getGraphicsContext()))
+      return;
+
     state.pushStateSet(getStateSet());
     state.apply();
     state.setActiveTextureUnit(0);
@@ -174,6 +178,10 @@ 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);
@@ -428,7 +436,7 @@ FGRenderer::init( void ) {
     glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
 
     if (viewer) {
-       viewer->getCamera()
+      viewer->getCamera()
            ->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
     } else {
        sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
@@ -797,6 +805,7 @@ FGRenderer::update( bool refresh_camera_settings ) {
     // 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());
@@ -845,8 +854,9 @@ FGRenderer::resize( int width, int height ) {
     }
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
     if (viewer)
-       viewer->getCamera()->getViewport()->setViewport(0, height - view_h,
-                                                       width, view_h);
+        ;
+  //       viewer->getCamera()->getViewport()->setViewport(0, height - view_h,
+//                                                         width, view_h);
     else
        sceneView->getViewport()->setViewport(0, height - view_h,
                                              width, view_h);
@@ -874,84 +884,6 @@ FGRenderer::resize( int width, int height ) {
 }
 
 
-// These are wrapper functions around ssgSetNearFar() and ssgSetFOV()
-// which will post process and rewrite the resulting frustum if we
-// want to do asymmetric view frustums.
-
-static void fgHackFrustum() {
-
-    // specify a percent of the configured view frustum to actually
-    // display.  This is a bit of a hack to achieve asymmetric view
-    // frustums.  For instance, if you want to display two monitors
-    // side by side, you could specify each with a double fov, a 0.5
-    // aspect ratio multiplier, and then the left side monitor would
-    // have a left_pct = 0.0, a right_pct = 0.5, a bottom_pct = 0.0,
-    // and a top_pct = 1.0.  The right side monitor would have a
-    // left_pct = 0.5 and a right_pct = 1.0.
-
-    static SGPropertyNode *left_pct
-        = fgGetNode("/sim/current-view/frustum-left-pct");
-    static SGPropertyNode *right_pct
-        = fgGetNode("/sim/current-view/frustum-right-pct");
-    static SGPropertyNode *bottom_pct
-        = fgGetNode("/sim/current-view/frustum-bottom-pct");
-    static SGPropertyNode *top_pct
-        = fgGetNode("/sim/current-view/frustum-top-pct");
-    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
-    double left, right;
-    double bottom, top;
-    double zNear, zFar;
-    if (viewer)
-       viewer->getCamera()->getProjectionMatrixAsFrustum(left, right,
-                                                         bottom, top,
-                                                         zNear, zFar);
-    else
-       sceneView->getProjectionMatrixAsFrustum(left, right, bottom, top,
-                                               zNear, zFar);
-    // cout << " l = " << f->getLeft()
-    //      << " r = " << f->getRight()
-    //      << " b = " << f->getBot()
-    //      << " t = " << f->getTop()
-    //      << " n = " << f->getNear()
-    //      << " f = " << f->getFar()
-    //      << endl;
-
-    double width = right - left;
-    double height = top - bottom;
-
-    double l, r, t, b;
-
-    if ( left_pct != NULL ) {
-        l = left + width * left_pct->getDoubleValue();
-    } else {
-        l = left;
-    }
-
-    if ( right_pct != NULL ) {
-        r = left + width * right_pct->getDoubleValue();
-    } else {
-        r = right;
-    }
-
-    if ( bottom_pct != NULL ) {
-        b = bottom + height * bottom_pct->getDoubleValue();
-    } else {
-        b = bottom;
-    }
-
-    if ( top_pct != NULL ) {
-        t = bottom + height * top_pct->getDoubleValue();
-    } else {
-        t = top;
-    }
-    if (viewer)
-       viewer->getCamera()->setProjectionMatrixAsFrustum(l, r, b, t,
-                                                         zNear, zFar);
-    else
-       sceneView->setProjectionMatrixAsFrustum(l, r, b, t, zNear, zFar);
-}
-
-
 // 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
@@ -972,17 +904,11 @@ void FGRenderer::setFOV( float w, float h ) {
     fov_height = h;
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
     if (viewer)
-       viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height,
-                                                             fov_width/fov_height,
-                                                             fov_near, fov_far);
+       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);
-    // fully specify the view frustum before hacking it (so we don't
-    // accumulate hacked effects
-    fgHackFrustum();
-//     sgEnviro.setFOV( w, h );
 }
 
 
@@ -996,36 +922,29 @@ n = 0.1;
     fov_far = f;
     osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
     if (viewer)
-       viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height,
-                                                             fov_width/fov_height,
-                                                             fov_near, fov_far);
-    else 
+       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);
 
-    // fully specify the view frustum before hacking it (so we don't
-    // accumulate hacked effects
-    fgHackFrustum();
 }
 
 bool
 FGRenderer::pick( unsigned x, unsigned y,
-                  std::vector<SGSceneryPick>& pickList )
+                  std::vector<SGSceneryPick>& pickList,
+                  const osgGA::GUIEventAdapter* ea )
 {
   osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
   // wipe out the return ...
   pickList.resize(0);
 
-  osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
-  if (!sceneData)
-    return false;
-  osg::Viewport* viewport = 0;
-  osg::Matrix projection;
-  osg::Matrix modelview;
-
   if (sceneView.valid()) {
-    viewport = sceneView->getViewport();
+    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,
@@ -1047,40 +966,64 @@ FGRenderer::pick( unsigned x, unsigned y,
     // 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) {
-    // I don't think the Viewer case needs to update the camera
-    // matrices before picking. The user has clicked on the old scene
-    // -- that which is displayed in the front buffer -- so we need to
-    // use the camera state in effect for that view of the scene.
-    osg::Camera *camera = viewer->getCamera();
-    viewport = camera->getViewport();
-    projection = camera->getProjectionMatrix();
-    modelview = camera->getViewMatrix();
-    // Accumulated transforms? Don't think that applies for the
-    // Viewer's camera.
-  } else {                     // we can get called early ...
-    return false;
-  }
-  // 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();
+    // just compute intersections in the viewers method ...
+    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);
@@ -1091,22 +1034,18 @@ FGRenderer::pick( unsigned x, unsigned y,
           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.info.local = SGVec3d(hit->getLocalIntersectPoint());
+          sceneryPick.info.wgs84 = SGVec3d(hit->getWorldIntersectPoint());
           sceneryPick.callback = pickCallback;
           pickList.push_back(sceneryPick);
         }
       }
     }
-  }
 
-  return !pickList.empty();
+    return !pickList.empty();
+  } else {                     // we can get called early ...
+    return false;
+  }
 }
 
 bool fgDumpSceneGraphToFile(const char* filename)
index 1ac1af354b869c9f0587b753132b19417cb37ee5..ea14d353405173aeb3e87bc5a9b92b7bcb452874 100644 (file)
@@ -54,7 +54,8 @@ public:
     /** Just pick into the scene and return the pick callbacks on the way ...
      */
     static bool pick( unsigned x, unsigned y,
-                      std::vector<SGSceneryPick>& pickList );
+                      std::vector<SGSceneryPick>& pickList,
+                      const osgGA::GUIEventAdapter* ea );
 
     /** Get and set the OSG Viewer object, if any.
      */