-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Howdy,
This patch implements the option of using OpenSceneGraph's osgViewer
instead of SDL or glut. The major user visible difference is the
availability of OSG statistics, as seen in
http://www.bricoworks.com/moore/osgstats.png, which show the time spent
in each major part of the update and rendering process and which can
help track down performance problems (hit the '*' key). The osgViewer
framework also allows very flexible view / camera / window configuration
and multithreading options which will be useful in the future. The one
loss of functionality with this patch is that the cursor can't be
changed; I'm looking into that.

Enjoy,
Tim

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iD8DBQFGSON1eDhWHdXrDRURAo/qAKCf5TE+vVoW6++0KmEYh7L9QAKV+gCg4csx
kFQYcAB/NimSig8Ij8HCP/8=
=S/k9
-----END PGP SIGNATURE-----
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/configure.ac fg/fgcvs/FlightGear/source/configure.ac
--- fgcvs/FlightGear/source/configure.ac	2007-01-06 19:44:25.000000000 +0100
+++ fg/fgcvs/FlightGear/source/configure.ac	2007-05-13 09:32:42.000000000 +0200
@@ -199,11 +199,18 @@
 
 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 -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/FGManipulator.cxx fg/fgcvs/FlightGear/source/src/Main/FGManipulator.cxx
--- fgcvs/FlightGear/source/src/Main/FGManipulator.cxx	1970-01-01 01:00:00.000000000 +0100
+++ fg/fgcvs/FlightGear/source/src/Main/FGManipulator.cxx	2007-05-14 23:17:43.000000000 +0200
@@ -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 -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/FGManipulator.hxx fg/fgcvs/FlightGear/source/src/Main/FGManipulator.hxx
--- fgcvs/FlightGear/source/src/Main/FGManipulator.hxx	1970-01-01 01:00:00.000000000 +0100
+++ fg/fgcvs/FlightGear/source/src/Main/FGManipulator.hxx	2007-05-13 08:49:58.000000000 +0200
@@ -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
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/fg_os.cxx fg/fgcvs/FlightGear/source/src/Main/fg_os.cxx
--- fgcvs/FlightGear/source/src/Main/fg_os.cxx	2006-03-10 08:13:59.000000000 +0100
+++ fg/fgcvs/FlightGear/source/src/Main/fg_os.cxx	2007-05-14 23:37:42.000000000 +0200
@@ -236,3 +236,7 @@
     glutReshapeFunc(GLUTreshape);
 }
 
+// Noop; the graphics context is always current
+void fgMakeCurrent()
+{
+}
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/fg_os.hxx fg/fgcvs/FlightGear/source/src/Main/fg_os.hxx
--- fgcvs/FlightGear/source/src/Main/fg_os.hxx	2004-04-25 04:17:03.000000000 +0200
+++ fg/fgcvs/FlightGear/source/src/Main/fg_os.hxx	2007-05-13 10:29:04.000000000 +0200
@@ -76,4 +76,5 @@
 void fgRegisterMouseClickHandler(fgMouseClickHandler func);
 void fgRegisterMouseMotionHandler(fgMouseMotionHandler func);
 
+void fgMakeCurrent();
 #endif // _FG_OS_HXX
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/fg_os_osgviewer.cxx fg/fgcvs/FlightGear/source/src/Main/fg_os_osgviewer.cxx
--- fgcvs/FlightGear/source/src/Main/fg_os_osgviewer.cxx	1970-01-01 01:00:00.000000000 +0100
+++ fg/fgcvs/FlightGear/source/src/Main/fg_os_osgviewer.cxx	2007-05-14 23:32:44.000000000 +0200
@@ -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();
+}
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/fg_os_sdl.cxx fg/fgcvs/FlightGear/source/src/Main/fg_os_sdl.cxx
--- fgcvs/FlightGear/source/src/Main/fg_os_sdl.cxx	2006-05-17 23:21:38.000000000 +0200
+++ fg/fgcvs/FlightGear/source/src/Main/fg_os_sdl.cxx	2007-05-14 23:36:57.000000000 +0200
@@ -407,3 +407,8 @@
                                                 cursors[i].hoty);
     }
 }
+
+// Noop; the graphics context is always current
+void fgMakeCurrent()
+{
+}
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/main.cxx fg/fgcvs/FlightGear/source/src/Main/main.cxx
--- fgcvs/FlightGear/source/src/Main/main.cxx	2007-05-14 15:31:20.000000000 +0200
+++ fg/fgcvs/FlightGear/source/src/Main/main.cxx	2007-05-14 15:36:35.000000000 +0200
@@ -603,6 +603,9 @@
 // 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++;
 
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/Makefile.am fg/fgcvs/FlightGear/source/src/Main/Makefile.am
--- fgcvs/FlightGear/source/src/Main/Makefile.am	2007-02-14 18:45:57.000000000 +0100
+++ fg/fgcvs/FlightGear/source/src/Main/Makefile.am	2007-05-13 01:34:06.000000000 +0200
@@ -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 @@
 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 @@
 	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 @@
 	-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 \
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/renderer.cxx fg/fgcvs/FlightGear/source/src/Main/renderer.cxx
--- fgcvs/FlightGear/source/src/Main/renderer.cxx	2007-05-14 15:31:20.000000000 +0200
+++ fg/fgcvs/FlightGear/source/src/Main/renderer.cxx	2007-05-15 00:22:15.000000000 +0200
@@ -358,6 +358,9 @@
 #ifdef FG_JPEG_SERVER
    jpgRenderFrame = FGRenderer::update;
 #endif
+#ifdef ENABLE_OSGVIEWER
+   manipulator = new FGManipulator;
+#endif   
 }
 
 FGRenderer::~FGRenderer()
@@ -368,20 +371,38 @@
 }
 
 // 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 @@
     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 @@
     mRealRoot->addChild(sw);
     mRealRoot->addChild(FGCreateRedoutNode());
     mRealRoot->addChild(guiCamera);
+//  sceneView->getState()->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
 }
 
 
@@ -529,7 +555,7 @@
 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 @@
         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 @@
         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 @@
 //         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 @@
                              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 @@
     } 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 @@
         = 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 @@
     } 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 @@
 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 @@
 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 @@
 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
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Main/renderer.hxx fg/fgcvs/FlightGear/source/src/Main/renderer.hxx
--- fgcvs/FlightGear/source/src/Main/renderer.hxx	2007-05-03 21:53:20.000000000 +0200
+++ fg/fgcvs/FlightGear/source/src/Main/renderer.hxx	2007-05-13 01:41:57.000000000 +0200
@@ -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 @@
      */
     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
diff -Pur -x CVS -x .cvsignore -x Makefile -x configure -x autom4te.cache -x '*~' -x Makefile.in fgcvs/FlightGear/source/src/Network/jpg-httpd.cxx fg/fgcvs/FlightGear/source/src/Network/jpg-httpd.cxx
--- fgcvs/FlightGear/source/src/Network/jpg-httpd.cxx	2007-02-10 17:32:21.000000000 +0100
+++ fg/fgcvs/FlightGear/source/src/Network/jpg-httpd.cxx	2007-05-14 14:08:57.000000000 +0200
@@ -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 @@
         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();
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel

Reply via email to