]> git.mxchange.org Git - flightgear.git/commitdiff
Modified Files:
authorfrohlich <frohlich>
Mon, 21 May 2007 17:50:02 +0000 (17:50 +0000)
committerfrohlich <frohlich>
Mon, 21 May 2007 17:50:02 +0000 (17:50 +0000)
configure.ac src/Main/Makefile.am src/Main/fg_os.cxx
src/Main/fg_os.hxx src/Main/fg_os_sdl.cxx src/Main/main.cxx
src/Main/renderer.cxx src/Main/renderer.hxx
src/Network/jpg-httpd.cxx
Added Files:
src/Main/FGManipulator.cxx src/Main/FGManipulator.hxx
src/Main/fg_os_osgviewer.cxx:
Tim Moore: Make use of osgViewer.

12 files changed:
configure.ac
src/Main/FGManipulator.cxx [new file with mode: 0644]
src/Main/FGManipulator.hxx [new file with mode: 0644]
src/Main/Makefile.am
src/Main/fg_os.cxx
src/Main/fg_os.hxx
src/Main/fg_os_osgviewer.cxx [new file with mode: 0644]
src/Main/fg_os_sdl.cxx
src/Main/main.cxx
src/Main/renderer.cxx
src/Main/renderer.hxx
src/Network/jpg-httpd.cxx

index 18ecf3a518eb3505bdd198d063087b261e659394..9a2b50ea71d30a0aaedf356ba209b11fd44fe88f 100644 (file)
@@ -199,11 +199,18 @@ base_LIBS="$LIBS"
 
 dnl Check for SDL if enabled.
 AC_ARG_ENABLE(sdl, [  --enable-sdl                  Configure to use SDL instead of GLUT], [enable_sdl="$enableval"])
+AC_ARG_ENABLE(osgviewer, [  --enable-osgviewer                  Configure to use osgViewer], [enable_osgviewer="$enableval"])
 AM_CONDITIONAL(USE_SDL, test "x$enable_sdl" = "xyes")
+AM_CONDITIONAL(USE_OSGVIEWER, test "x$enable_osgviewer" = "xyes")
 if test "x$enable_sdl" = "xyes"; then
     AC_DEFINE([PU_USE_SDL], 1, [Define to use SDL])
 else
-    AC_DEFINE([PU_USE_GLUT], 1, [Define to use glut])
+    if test "x$enable_osgviewer" = "xyes"; then
+       AC_DEFINE([ENABLE_OSGVIEWER], 1, [Define to use osgViewer in renderer])
+       AC_DEFINE([PU_USE_NATIVE], 1, [Define to use native system])
+    else
+        AC_DEFINE([PU_USE_GLUT], 1, [Define to use glut])
+    fi
 fi
 
 dnl check for OpenGL related libraries
diff --git a/src/Main/FGManipulator.cxx b/src/Main/FGManipulator.cxx
new file mode 100644 (file)
index 0000000..e4a551f
--- /dev/null
@@ -0,0 +1,181 @@
+#include <osg/Math>
+
+#include <osgViewer/Viewer>
+
+#include <plib/pu.h>
+#include "FGManipulator.hxx"
+
+// The manipulator is responsible for updating a Viewer's camera. It's
+// event handling method is also a convenient place to run the the FG
+// idle and draw handlers.
+
+void FGManipulator::setByMatrix(const osg::Matrixd& matrix)
+{
+    // Yuck
+    position = matrix.getTrans();
+    attitude = matrix.getRotate();
+}
+
+osg::Matrixd FGManipulator::getMatrix() const
+{
+    return osg::Matrixd::rotate(attitude) * osg::Matrixd::translate(position);
+}
+
+osg::Matrixd FGManipulator::getInverseMatrix() const
+{
+    return (osg::Matrixd::translate(-position)
+           * osg::Matrixd::rotate(attitude.inverse())) ;
+}
+
+// Not used, but part of the interface.
+void FGManipulator::setNode(osg::Node* node)
+{
+    _node = node;
+}
+    
+const osg::Node* FGManipulator::getNode() const
+{
+    return _node.get();
+}
+
+osg::Node* FGManipulator::getNode()
+{
+    return _node.get();
+}
+
+namespace {
+// All the usual translation from window system to FG / plib
+int osgToFGModifiers(int modifiers)
+{
+    int result = 0;
+    if (modifiers & (osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT |
+                    osgGA::GUIEventAdapter::MODKEY_RIGHT_SHIFT))
+       result |= KEYMOD_SHIFT;
+    if (modifiers & (osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL |
+                    osgGA::GUIEventAdapter::MODKEY_RIGHT_CTRL))
+       result |= KEYMOD_CTRL;
+    if (modifiers & (osgGA::GUIEventAdapter::MODKEY_LEFT_ALT |
+                    osgGA::GUIEventAdapter::MODKEY_RIGHT_ALT))
+       result |= KEYMOD_ALT;
+    return result;
+}
+} // namespace
+
+void FGManipulator::init(const osgGA::GUIEventAdapter& ea,
+                        osgGA::GUIActionAdapter& us)
+{
+    currentModifiers = osgToFGModifiers(ea.getModKeyMask());
+    (void)handle(ea, us);
+}
+
+namespace {
+void eventToViewport(const osgGA::GUIEventAdapter& ea,
+                    osgGA::GUIActionAdapter& us,
+                    int& x, int& y)
+{
+    osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&us);
+    osg::Viewport* viewport = viewer->getCamera()->getViewport();
+    const osg::GraphicsContext::Traits* traits
+       = viewer->getCamera()->getGraphicsContext()->getTraits();
+    x = (int)ea.getX();
+    y = (int)ea.getY();
+    if (ea.getMouseYOrientation()
+       == osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS)
+       y = (int)traits->height - y;
+}
+}
+
+bool FGManipulator::handle(const osgGA::GUIEventAdapter& ea,
+                          osgGA::GUIActionAdapter& us)
+{
+    int x, y;
+    switch (ea.getEventType()) {
+    case osgGA::GUIEventAdapter::FRAME:
+       if (idleHandler)
+           (*idleHandler)();
+       if (drawHandler)
+           (*drawHandler)();
+       return true;
+    case osgGA::GUIEventAdapter::KEYDOWN:
+    case osgGA::GUIEventAdapter::KEYUP:
+    {
+       int key, modmask;
+       handleKey(ea, key, modmask);
+       eventToViewport(ea, us, x, y);
+       if (keyHandler)
+           (*keyHandler)(key, modmask, x, y);
+    }
+    return true;
+    case osgGA::GUIEventAdapter::PUSH:
+    case osgGA::GUIEventAdapter::RELEASE:
+    {
+       eventToViewport(ea, us, x, y);
+       int button = 0;
+       switch (ea.getButton()) {
+       case osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON:
+           button = 0;
+           break;
+       case osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON:
+           button = 1;
+           break;
+       case osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON:
+           button = 2;
+           break;
+       }
+       if (mouseClickHandler)
+           (*mouseClickHandler)(button,
+                                (ea.getEventType()
+                                 == osgGA::GUIEventAdapter::RELEASE), x, y);
+       return true;
+    }
+    case osgGA::GUIEventAdapter::MOVE:
+    case osgGA::GUIEventAdapter::DRAG:
+       eventToViewport(ea, us, x, y);
+       if (mouseMotionHandler)
+           (*mouseMotionHandler)(x, y);
+       return true;
+    case osgGA::GUIEventAdapter::RESIZE:
+       if (windowResizeHandler)
+           (*windowResizeHandler)(ea.getWindowWidth(), ea.getWindowHeight());
+       return true;
+    default:
+       return false;
+    }
+}
+           
+void FGManipulator::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
+                             int& modifiers)
+{
+    key = ea.getKey();
+    // XXX Probably other translations are needed too.
+    switch (key) {
+    case osgGA::GUIEventAdapter::KEY_Escape: key = 0x1b; break;
+    case osgGA::GUIEventAdapter::KEY_Return: key = '\n'; break;
+    case osgGA::GUIEventAdapter::KEY_Left:     key = PU_KEY_LEFT;      break;
+    case osgGA::GUIEventAdapter::KEY_Up:       key = PU_KEY_UP;        break;
+    case osgGA::GUIEventAdapter::KEY_Right:    key = PU_KEY_RIGHT;     break;
+    case osgGA::GUIEventAdapter::KEY_Down:     key = PU_KEY_DOWN;      break;
+    case osgGA::GUIEventAdapter::KEY_Page_Up:   key = PU_KEY_PAGE_UP;   break;
+    case osgGA::GUIEventAdapter::KEY_Page_Down: key = PU_KEY_PAGE_DOWN; break;
+    case osgGA::GUIEventAdapter::KEY_Home:     key = PU_KEY_HOME;      break;
+    case osgGA::GUIEventAdapter::KEY_End:      key = PU_KEY_END;       break;
+    case osgGA::GUIEventAdapter::KEY_Insert:   key = PU_KEY_INSERT;    break;
+    case osgGA::GUIEventAdapter::KEY_F1:       key = PU_KEY_F1;        break;
+    case osgGA::GUIEventAdapter::KEY_F2:       key = PU_KEY_F2;        break;
+    case osgGA::GUIEventAdapter::KEY_F3:       key = PU_KEY_F3;        break;
+    case osgGA::GUIEventAdapter::KEY_F4:       key = PU_KEY_F4;        break;
+    case osgGA::GUIEventAdapter::KEY_F5:       key = PU_KEY_F5;        break;
+    case osgGA::GUIEventAdapter::KEY_F6:       key = PU_KEY_F6;        break;
+    case osgGA::GUIEventAdapter::KEY_F7:       key = PU_KEY_F7;        break;
+    case osgGA::GUIEventAdapter::KEY_F8:       key = PU_KEY_F8;        break;
+    case osgGA::GUIEventAdapter::KEY_F9:       key = PU_KEY_F9;        break;
+    case osgGA::GUIEventAdapter::KEY_F10:      key = PU_KEY_F10;       break;
+    case osgGA::GUIEventAdapter::KEY_F11:      key = PU_KEY_F11;       break;
+    case osgGA::GUIEventAdapter::KEY_F12:      key = PU_KEY_F12;       break;
+    }
+    modifiers = osgToFGModifiers(ea.getModKeyMask());
+    currentModifiers = modifiers;
+    if (ea.getEventType() == osgGA::GUIEventAdapter::KEYUP)
+       modifiers |= KEYMOD_RELEASED;
+}
+
diff --git a/src/Main/FGManipulator.hxx b/src/Main/FGManipulator.hxx
new file mode 100644 (file)
index 0000000..dae69d2
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef FGMANIPULATOR_H
+#define FGMANIPULATOR_H 1
+
+#include <osg/Quat>
+#include <osgGA/MatrixManipulator>
+
+#include "fg_os.hxx"
+
+class FGManipulator : public osgGA::MatrixManipulator {
+public:
+    FGManipulator() :
+       idleHandler(0), drawHandler(0), windowResizeHandler(0), keyHandler(0),
+       mouseClickHandler(0), mouseMotionHandler(0), currentModifiers(0)
+       {}
+    virtual ~FGManipulator() {}
+    
+    virtual const char* className() const {return "FGManipulator"; }
+
+    /** set the position of the matrix manipulator using a 4x4 Matrix.*/
+    virtual void setByMatrix(const osg::Matrixd& matrix);
+
+    virtual void setByInverseMatrix(const osg::Matrixd& matrix)
+       { setByMatrix(osg::Matrixd::inverse(matrix)); }
+
+    /** get the position of the manipulator as 4x4 Matrix.*/
+    virtual osg::Matrixd getMatrix() const;
+
+    /** get the position of the manipulator as a inverse matrix of the manipulator, typically used as a model view matrix.*/
+    virtual osg::Matrixd getInverseMatrix() const;
+
+    virtual void setNode(osg::Node* node);
+    
+    const osg::Node* getNode() const;
+
+    osg::Node* getNode();
+
+    virtual void init(const osgGA::GUIEventAdapter& ea,
+                     osgGA::GUIActionAdapter& us);
+
+    virtual bool handle(const osgGA::GUIEventAdapter& ea,
+                       osgGA::GUIActionAdapter& us);
+
+    void setIdleHandler(fgIdleHandler idleHandler)
+       {
+           this->idleHandler = idleHandler;
+       }
+
+    fgIdleHandler getIdleHandler() const
+       {
+           return idleHandler;
+       }
+
+    void setDrawHandler(fgDrawHandler drawHandler)
+       {
+           this->drawHandler = drawHandler;
+       }
+
+    fgDrawHandler getDrawHandler() const
+       {
+           return drawHandler;
+       }
+
+    void setWindowResizeHandler(fgWindowResizeHandler windowResizeHandler)
+       {
+           this->windowResizeHandler = windowResizeHandler;
+       }
+    
+    fgWindowResizeHandler getWindowResizeHandler() const
+       {
+           return windowResizeHandler;
+       }
+
+    void setKeyHandler(fgKeyHandler keyHandler)
+       {
+           this->keyHandler = keyHandler;
+       }
+
+    fgKeyHandler getKeyHandler() const
+       {
+           return keyHandler;
+       }
+
+    void setMouseClickHandler(fgMouseClickHandler mouseClickHandler)
+       {
+           this->mouseClickHandler = mouseClickHandler;
+       }
+    
+    fgMouseClickHandler getMouseClickHandler()
+       {
+           return mouseClickHandler;
+       }
+
+    void setMouseMotionHandler(fgMouseMotionHandler mouseMotionHandler)
+       {
+           this->mouseMotionHandler = mouseMotionHandler;
+       }
+    
+    fgMouseMotionHandler getMouseMotionHandler()
+       {
+           return mouseMotionHandler;
+       }
+
+    int getCurrentModifiers() const
+       {
+           return currentModifiers;
+       }
+    void setPosition(const osg::Vec3d position) { this->position = position; }
+    void setAttitude(const osg::Quat attitude) { this->attitude = attitude; }
+
+protected:
+    osg::ref_ptr<osg::Node> _node;
+    fgIdleHandler idleHandler;
+    fgDrawHandler drawHandler;
+    fgWindowResizeHandler windowResizeHandler;
+    fgKeyHandler keyHandler;
+    fgMouseClickHandler mouseClickHandler;
+    fgMouseMotionHandler mouseMotionHandler;
+    int currentModifiers;
+    osg::Vec3d position;
+    osg::Quat attitude;
+    void handleKey(const osgGA::GUIEventAdapter& ea, int& key, int& modifiers);
+
+};
+#endif
index f420d7fd179e14a8c0106029a02746674938aa8d..e9c8e6becc72f3a1344cd2651b8bcb6f41a0a112 100644 (file)
@@ -1,5 +1,5 @@
 EXTRA_DIST = 3dfx.sh runfgfs.in runfgfs.bat.in \
-             fg_os_sdl.cxx fg_os.cxx fg_os.hxx
+             fg_os_sdl.cxx fg_os.cxx fg_os_osgviewer.cxx fg_os.hxx
 
 MPLAYER_LIBS = $(top_builddir)/src/MultiPlayer/libMultiPlayer.a
 
@@ -18,8 +18,12 @@ endif
 if USE_SDL
 GFX_CODE = fg_os_sdl.cxx fg_os.hxx
 else
+if USE_OSGVIEWER
+GFX_CODE = fg_os_osgviewer.cxx fg_os.hxx
+else
 GFX_CODE = fg_os.cxx fg_os.hxx
 endif
+endif
 
 JSBSIM_LIBS = \
        $(top_builddir)/src/FDM/JSBSim/libJSBSim.a \
@@ -55,6 +59,7 @@ libMain_a_SOURCES = \
        util.cxx util.hxx \
        viewer.cxx viewer.hxx \
        viewmgr.cxx viewmgr.hxx \
+       FGManipulator.cxx FGManipulator.hxx \
        $(GFX_CODE)
 
 fgfs_SOURCES = bootstrap.cxx
@@ -99,7 +104,7 @@ fgfs_LDADD = \
        -lsgstructure -lsgenvironment \
        -lplibpuaux -lplibpu -lplibfnt -lplibjs -lplibnet \
        -lplibsg -lplibul \
-       -losgUtil -losgDB -losgSim -losg -lOpenThreads \
+       -losgViewer -losgFX -losgUtil -losgDB -losgSim -losg -lOpenThreads \
        $(THREAD_LIBS) \
        $(network_LIBS) \
        -lz \
index d60f153eff40c95807539f480defb0b2165fa420..26767fcc4554dcab108d0397650ee548a8a95259 100644 (file)
@@ -236,3 +236,7 @@ void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
     glutReshapeFunc(GLUTreshape);
 }
 
+// Noop; the graphics context is always current
+void fgMakeCurrent()
+{
+}
index 5b5df9c398658e66f16231c95737c52363c9d535..931dcb10fedf1780dd30ace7699ce29dd53f7412 100644 (file)
@@ -76,4 +76,5 @@ void fgRegisterKeyHandler(fgKeyHandler func);
 void fgRegisterMouseClickHandler(fgMouseClickHandler func);
 void fgRegisterMouseMotionHandler(fgMouseMotionHandler func);
 
+void fgMakeCurrent();
 #endif // _FG_OS_HXX
diff --git a/src/Main/fg_os_osgviewer.cxx b/src/Main/fg_os_osgviewer.cxx
new file mode 100644 (file)
index 0000000..1206472
--- /dev/null
@@ -0,0 +1,165 @@
+#include <stdlib.h>
+
+#include <simgear/compiler.h>
+#include <simgear/structure/exception.hxx>
+#include <simgear/debug/logstream.hxx>
+
+#include <osg/GraphicsContext>
+#include <osg/Group>
+#include <osg/Matrixd>
+#include <osg/Viewport>
+#include <osgViewer/StatsHandler>
+#include <osgViewer/Viewer>
+#include <osgGA/MatrixManipulator>
+
+#include "fg_os.hxx"
+#include "util.hxx"
+#include "globals.hxx"
+#include "renderer.hxx"
+
+// fg_os implementation using OpenSceneGraph's osgViewer::Viewer class
+// to create the graphics window and run the event/update/render loop.
+//
+// fg_os callback registration APIs
+//
+
+
+// Event handling and scene graph update is all handled by a
+// manipulator. See FGManipulator.cpp
+void fgRegisterIdleHandler(fgIdleHandler func)
+{
+    globals->get_renderer()->getManipulator()->setIdleHandler(func);
+}
+
+void fgRegisterDrawHandler(fgDrawHandler func)
+{
+    globals->get_renderer()->getManipulator()->setDrawHandler(func);
+}
+
+void fgRegisterWindowResizeHandler(fgWindowResizeHandler func)
+{
+    globals->get_renderer()->getManipulator()->setWindowResizeHandler(func);
+}
+
+void fgRegisterKeyHandler(fgKeyHandler func)
+{
+    globals->get_renderer()->getManipulator()->setKeyHandler(func);
+}
+
+void fgRegisterMouseClickHandler(fgMouseClickHandler func)
+{
+    globals->get_renderer()->getManipulator()->setMouseClickHandler(func);
+}
+
+void fgRegisterMouseMotionHandler(fgMouseMotionHandler func)
+{
+    globals->get_renderer()->getManipulator()->setMouseMotionHandler(func);
+}
+
+// Redraw "happens" every frame whether you want it or not.
+void fgRequestRedraw()
+{
+}
+
+//
+// fg_os implementation
+//
+
+
+static osg::ref_ptr<osgViewer::Viewer> viewer;
+
+void fgOSOpenWindow(int w, int h, int bpp,
+                    bool alpha, bool stencil, bool fullscreen)
+{
+    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;
+    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->windowDecoration = false;
+    else
+       traits->windowDecoration = true;
+    traits->supportsResize = true;
+    traits->doubleBuffer = true;
+    osg::GraphicsContext* gc
+       = osg::GraphicsContext::createGraphicsContext(traits.get());
+    viewer->getCamera()->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));
+    viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
+    // Let FG handle the escape key with a confirmation
+    viewer->setKeyEventSetsDone(0);
+    osgViewer::StatsHandler* statsHandler = new osgViewer::StatsHandler;
+    statsHandler->setKeyEventTogglesOnScreenStats('*');
+    statsHandler->setKeyEventPrintsOutStats(0);
+    viewer->addEventHandler(statsHandler);
+    // The viewer won't start without some root.
+    viewer->setSceneData(new osg::Group);
+    globals->get_renderer()->setViewer(viewer.get());
+}
+
+static int status = 0;
+
+void fgOSExit(int code)
+{
+    viewer->setDone(true);
+    status = code;
+}
+
+void fgOSMainLoop()
+{
+    viewer->run();
+    fgExit(status);
+}
+
+int fgGetKeyModifiers()
+{
+    return globals->get_renderer()->getManipulator()->getCurrentModifiers();
+}
+
+void fgWarpMouse(int x, int y)
+{
+    viewer->requestWarpPointer((float)x, (float)y);
+}
+
+// Noop
+void fgOSInit(int* argc, char** argv)
+{
+}
+
+void fgOSFullScreen()
+{
+    // Noop, but is probably doable
+
+}
+
+// No support in OSG yet
+void fgSetMouseCursor(int cursor)
+{
+}
+
+int fgGetMouseCursor()
+{
+    return 0;
+}
+
+void fgMakeCurrent()
+{
+    osg::GraphicsContext* gc = viewer->getCamera()->getGraphicsContext();
+    gc->makeCurrent();
+}
index dcb9c654141048ed8a57b4710936f593e98faf6a..e9ad6f7759094b649990598405eb43fd1fb2ae99 100644 (file)
@@ -407,3 +407,8 @@ static void initCursors()
                                                 cursors[i].hoty);
     }
 }
+
+// Noop; the graphics context is always current
+void fgMakeCurrent()
+{
+}
index cd5bba53a2a74ca409bb926a92105e206fbe15f0..ffb8d499bfb9a631e06135eb01c0b861b58d2635 100644 (file)
@@ -603,6 +603,9 @@ static void fgMainLoop( void ) {
 // then on.
 
 static void fgIdleFunction ( void ) {
+    // Some intialization requires a valid graphics context, in
+    // particular that of plib. Boo, hiss!
+    fgMakeCurrent();
     if ( idle_state == 0 ) {
         idle_state++;
 
index b6a8c6f0761bc538e6668badd8d56689da3f5ef9..b0ba33414b036fdca60a75f6ade6ea7eb651117b 100644 (file)
@@ -358,6 +358,9 @@ FGRenderer::FGRenderer()
 #ifdef FG_JPEG_SERVER
    jpgRenderFrame = FGRenderer::update;
 #endif
+#ifdef ENABLE_OSGVIEWER
+   manipulator = new FGManipulator;
+#endif   
 }
 
 FGRenderer::~FGRenderer()
@@ -368,20 +371,38 @@ FGRenderer::~FGRenderer()
 }
 
 // Initialize various GL/view parameters
+// XXX This should be called "preinit" or something, as it initializes
+// critical parts of the scene graph in addition to the splash screen.
 void
 FGRenderer::splashinit( void ) {
-   // 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());
+    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();
+       scene->setFrameStamp(mFrameStamp.get());
+       // 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());
+    }
 }
 
 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();
+    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
     osg::initNotifyLevel();
 
     // The number of polygon-offset "units" to place between layers.  In
@@ -406,9 +427,13 @@ FGRenderer::init( void ) {
     glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
     glHint(GL_POINT_SMOOTH_HINT, GL_DONT_CARE);
 
-
-    sceneView->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
-    sceneView->getCamera()->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
+    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);
+    }
 
 
     osg::StateSet* stateSet = mRoot->getOrCreateStateSet();
@@ -521,6 +546,7 @@ FGRenderer::init( void ) {
     mRealRoot->addChild(sw);
     mRealRoot->addChild(FGCreateRedoutNode());
     mRealRoot->addChild(guiCamera);
+//  sceneView->getState()->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
 }
 
 
@@ -529,7 +555,7 @@ void
 FGRenderer::update( bool refresh_camera_settings ) {
     bool scenery_loaded = fgGetBool("sim/sceneryloaded")
                           || fgGetBool("sim/sceneryloaded-override");
-
+    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
     if ( idle_state < 1000 || !scenery_loaded ) {
         fgSetDouble("/sim/startup/splash-alpha", 1.0);
 
@@ -537,10 +563,11 @@ FGRenderer::update( bool refresh_camera_settings ) {
         globals->set_sim_time_sec( 0.0 );
 
         // the splash screen is now in the scenegraph
-        sceneView->update();
-        sceneView->cull();
-        sceneView->draw();
-
+       if (!viewer) {
+           sceneView->update();
+           sceneView->cull();
+           sceneView->draw();
+       }
         return;
     }
 
@@ -586,18 +613,30 @@ FGRenderer::update( bool refresh_camera_settings ) {
         SGVec3d position = current__view->getViewPosition();
         SGQuatd attitude = current__view->getViewOrientation();
         SGVec3d osgPosition = attitude.transform(-position);
-        mCameraView->setPosition(osgPosition.osg());
-        mCameraView->setAttitude(inverse(attitude).osg());
+       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();
     if ( skyblend ) {
+       
         if ( fgGetBool("/sim/rendering/textures") ) {
             SGVec4f clearColor(l->adj_fog_color());
-            sceneView->getCamera()->setClearColor(clearColor.osg());
+            camera->setClearColor(clearColor.osg());
         }
     } else {
         SGVec4f clearColor(l->sky_color());
-        sceneView->getCamera()->setClearColor(clearColor.osg());
+        camera->setClearColor(clearColor.osg());
     }
 
     // update fog params if visibility has changed
@@ -756,8 +795,10 @@ FGRenderer::update( bool refresh_camera_settings ) {
 //         shadows->endOfFrame();
 
     // need to call the update visitor once
-    mFrameStamp->setReferenceTime(globals->get_sim_time_sec());
-    mFrameStamp->setFrameNumber(1+mFrameStamp->getFrameNumber());
+    if (!viewer) {
+       mFrameStamp->setReferenceTime(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());
@@ -767,15 +808,24 @@ FGRenderer::update( bool refresh_camera_settings ) {
                              l->adj_fog_color(),
                              l->get_sun_angle()*SGD_RADIANS_TO_DEGREES);
     mUpdateVisitor->setVisibility(actual_visibility);
-
-    if (fgGetBool("/sim/panel-hotspots"))
-      sceneView->setCullMask(sceneView->getCullMask()|SG_NODEMASK_PICK_BIT);
-    else
-      sceneView->setCullMask(sceneView->getCullMask()&(~SG_NODEMASK_PICK_BIT));
-
-    sceneView->update();
-    sceneView->cull();
-    sceneView->draw();
+    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();
+    }
 }
 
 
@@ -793,8 +843,13 @@ FGRenderer::resize( int width, int height ) {
     } else {
         view_h = height;
     }
-
-    sceneView->getViewport()->setViewport(0, height - view_h, width, view_h);
+    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;
@@ -842,11 +897,17 @@ static void fgHackFrustum() {
         = 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;
-    sceneView->getProjectionMatrixAsFrustum(left, right, bottom, top, 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()
@@ -883,8 +944,11 @@ static void fgHackFrustum() {
     } else {
         t = top;
     }
-
-    sceneView->setProjectionMatrixAsFrustum(l, r, b, t, zNear, zFar);
+    if (viewer)
+       viewer->getCamera()->setProjectionMatrixAsFrustum(l, r, b, t,
+                                                         zNear, zFar);
+    else
+       sceneView->setProjectionMatrixAsFrustum(l, r, b, t, zNear, zFar);
 }
 
 
@@ -906,10 +970,15 @@ static float fov_far = 1000.0;
 void FGRenderer::setFOV( float w, float h ) {
     fov_width = w;
     fov_height = h;
-
-    sceneView->setProjectionMatrixAsPerspective(fov_height,
-                                                fov_width/fov_height,
-                                                fov_near, fov_far);
+    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+    if (viewer)
+       viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height,
+                                                             fov_width/fov_height,
+                                                             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();
@@ -925,10 +994,15 @@ void FGRenderer::setNearFar( float n, float f ) {
 n = 0.1;
     fov_near = n;
     fov_far = f;
-
-    sceneView->setProjectionMatrixAsPerspective(fov_height,
-                                                fov_width/fov_height,
-                                                fov_near, fov_far);
+    osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+    if (viewer)
+       viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height,
+                                                             fov_width/fov_height,
+                                                             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
@@ -939,40 +1013,54 @@ bool
 FGRenderer::pick( unsigned x, unsigned y,
                   std::vector<SGSceneryPick>& pickList )
 {
+  osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
   // wipe out the return ...
   pickList.resize(0);
 
-  // we can get called early ...
-  if (!sceneView.valid())
-    return false;
-
   osg::Node* sceneData = globals->get_scenery()->get_scene_graph();
   if (!sceneData)
     return false;
-  osg::Viewport* viewport = sceneView->getViewport();
-  if (!viewport)
+  osg::Viewport* viewport = 0;
+  osg::Matrix projection;
+  osg::Matrix modelview;
+
+  if (sceneView.valid()) {
+    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()));
+  } 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;
-
-  // 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
index 02e0f6982ddea882ac6762bf84693d1ed90b653b..7bc54bfe94caa1f984847dc8e46ef19ac9bfc3f7 100644 (file)
@@ -6,6 +6,10 @@
 #include <simgear/scene/sky/sky.hxx>
 #include <simgear/scene/util/SGPickCallback.hxx>
 
+#include <osgViewer/Viewer>
+
+#include "FGManipulator.hxx"
+
 #define FG_ENABLE_MULTIPASS_CLOUDS 1
 
 class SGSky;
@@ -51,6 +55,23 @@ public:
      */
     static bool pick( unsigned x, unsigned y,
                       std::vector<SGSceneryPick>& pickList );
+
+    /** Get and set the OSG Viewer object, if any.
+     */
+    osgViewer::Viewer* getViewer() { return viewer.get(); }
+    const osgViewer::Viewer* getViewer() const { return viewer.get(); }
+    void setViewer(osgViewer::Viewer* viewer) { this->viewer = viewer; }
+    /** Get and set the manipulator object, if any.
+     */
+    FGManipulator* getManipulator() { return manipulator.get(); }
+    const FGManipulator* getManipulator() const { return manipulator.get(); }
+    void setManipulator(FGManipulator* manipulator)
+       {
+           this->manipulator = manipulator;
+       }
+protected:
+    osg::ref_ptr<osgViewer::Viewer> viewer;
+    osg::ref_ptr<FGManipulator> manipulator;
 };
 
 #endif
index 0516dd8189f1f18293bab1982cfe744d0c207ea7..9c83d3446686a731377e5772bbedef14ca2b8409 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
+#include <Main/renderer.hxx>
 
 #include "jpg-httpd.hxx"
 
@@ -106,7 +107,15 @@ void HttpdImageChannel :: foundTerminator( void ) {
         SG_LOG( SG_IO, SG_DEBUG, "<<<<<<<<< HTTP Request : " << pRequest );
 
         double left, right, bottom, top, zNear, zFar;
-        sceneView->getCamera()->getProjectionMatrixAsFrustum( left, right, bottom, top, zNear, zFar );
+       osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
+       if (viewer)
+           viewer->getCamera()->getProjectionMatrixAsFrustum(left, right,
+                                                             bottom, top,
+                                                             zNear, zFar);
+       else
+           sceneView->getCamera()->getProjectionMatrixAsFrustum(left, right,
+                                                                bottom, top,
+                                                                zNear, zFar);
         JpgFactory->setFrustum( left, right, bottom, top, zNear, zFar );
 
         nImageLen  = JpgFactory -> render();