1
0
Fork 0

Clean up OSG camera setup and interface to plib PUI

Switch to defining PU_USE_NONE and providing our own callback
functions to pui for "get window" and "get window size." A new
WindowSystemAdapter class assigns ID numbers to windows for the
purpose of identifying them to plib; the window size can be extracted
from the osg::GraphicsContext class in all the different
implementations (osgViewer, glut, sdl).

Implement a GraphicsContextOperation that runs code in a particular
graphics context, perhaps in another thread, and provides an
isFinished() method to test if the operation has finished. This allows
us to initialize plib PUI properly if there are multiple graphics
contexts without using fgMakeCurrent(). fgMakeCurrent() can't work in
multi-threaded OSG configurations.

Eliminate fgMakeCurrent() and all its uses, either by using
GraphicsContextOperation or by seeing that it is not necessary.

Attach the GUI camera as a slave camera.

Don't manipulate the OSG state in the drawImplementation() functions
for SGHUDAndPanelDrawable and SGPuDrawable; it's not needed.
This commit is contained in:
timoore 2008-05-19 21:21:03 +00:00
parent c92dcc6b24
commit 580ebf637b
18 changed files with 649 additions and 295 deletions

View file

@ -206,17 +206,14 @@ AM_CONDITIONAL(USE_GLUT, test "x$enable_glut" = "xyes")
if test "x$enable_sdl" != "xyes" -a "x$enable_glut" != "xyes" -a "x$enable_osgviewer" != "xno"; then
enable_osgviewer="yes"
fi
if test "x$enable_osgviewer" = "xyes"; then
AC_DEFINE([USE_OSGVIEWER], 1, [Define to use osgViewer in renderer])
AC_DEFINE([ENABLE_OSGVIEWER], 1, [Define to use osgViewer in renderer])
AC_DEFINE([PU_USE_NATIVE], 1, [Define to use native system])
elif test "x$enable_sdl" = "xyes"; then
AC_DEFINE([PU_USE_SDL], 1, [Define to use SDL])
elif test "x$enable_glut" = "xyes"; then
AC_DEFINE([PU_USE_GLUT], 1, [Define to use glut])
else
AC_MSG_ERROR([One (and only one) of --enable-osgviewer, --enable-sdl, or --enable-glut must be supplied])
if test \( "x$enable_osgviewer" = "xyes" \
-a \( "x$enable_sdl" = "xyes" -o "x$enable_glut" = "xyes" \) \) \
-o \( "x$enable_sdl" = "xyes" -a "x$enable_glut" = "xyes" \); then
echo " Only one of --enable-osgviewer, --enable-sdl, or --enable -glut may"
echo " be supplied."
exit
fi
AC_DEFINE([PU_USE_NONE], 1, [Define to use application's pu callbacks])
AC_ARG_ENABLE(osgdebug, [ --enable-osgdebug Use OSG debug libraries], [enable_osgdebug="$enableval"])

View file

@ -24,7 +24,7 @@
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..;..\..\src;..\..\src\include;..\..\..\SimGear;"..\..\..\pthreads-w32-2-7-0-release";..\..\src\FDM\JSBSim;..\..\..\OpenSceneGraph\include;..\..\..\OpenThreads\include;..\..\..\3rdParty\include"
PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;HAVE_CONFIG_H;FGFS;ENABLE_AUDIO_SUPPORT;_FG_NDEBUG;ENABLE_THREADS=1;FG_ENABLE_MULTIPASS_CLOUDS;ENABLE_SP_FMDS;_USE_MATH_DEFINES;FG_JPEG_SERVER;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ENABLE_OSGVIEWER;PU_USE_NATIVE"
PreprocessorDefinitions="_DEBUG;WIN32;_CONSOLE;HAVE_CONFIG_H;FGFS;ENABLE_AUDIO_SUPPORT;_FG_NDEBUG;ENABLE_THREADS=1;FG_ENABLE_MULTIPASS_CLOUDS;ENABLE_SP_FMDS;_USE_MATH_DEFINES;FG_JPEG_SERVER;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
StringPooling="TRUE"
BasicRuntimeChecks="0"
RuntimeLibrary="3"
@ -88,7 +88,7 @@
Name="VCCLCompilerTool"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\..\..;..\..\src;..\..\src\include;..\..\src\FDM\JSBSim;..\..\..\SimGear;"..\..\..\pthreads-w32-2-7-0-release";..\..\..\OpenSceneGraph\include;..\..\..\Producer\include;..\..\..\OpenThreads\include;..\..\..\3rdParty\include"
PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;HAVE_CONFIG_H;FGFS;ENABLE_AUDIO_SUPPORT;_FG_NDEBUG;ENABLE_THREADS=1;FG_ENABLE_MULTIPASS_CLOUDS;ENABLE_SP_FMDS;_USE_MATH_DEFINES;FG_JPEG_SERVER;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ENABLE_OSGVIEWER;PU_USE_NATIVE"
PreprocessorDefinitions="NDEBUG;WIN32;_CONSOLE;HAVE_CONFIG_H;FGFS;ENABLE_AUDIO_SUPPORT;_FG_NDEBUG;ENABLE_THREADS=1;FG_ENABLE_MULTIPASS_CLOUDS;ENABLE_SP_FMDS;_USE_MATH_DEFINES;FG_JPEG_SERVER;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
StringPooling="TRUE"
RuntimeLibrary="2"
EnableFunctionLevelLinking="TRUE"

View file

@ -566,7 +566,7 @@ void fgCockpitUpdate( osg::State* state ) {
struct FuncTable {
char *name;
const char *name;
FLTFNPTR func;
} fn_table[] = {
{ "agl", get_agl },

View file

@ -34,6 +34,8 @@
# include <windows.h>
#endif
#include <string>
#include <simgear/structure/exception.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx>
@ -45,12 +47,15 @@
#include <Main/main.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Main/WindowSystemAdapter.hxx>
#include <GUI/new_gui.hxx>
#include "gui.h"
#include "gui_local.hxx"
#include "layout.hxx"
using namespace osg;
using namespace flightgear;
puFont guiFnt = 0;
@ -59,48 +64,76 @@ puFont guiFnt = 0;
init the gui
_____________________________________________________________________*/
void guiInit()
namespace
{
char *mesa_win_state;
class GUIInitOperation : public GraphicsContextOperation
{
public:
GUIInitOperation() : GraphicsContextOperation(std::string("GUI init"))
{
}
void run(GraphicsContext* gc)
{
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
wsa->puInitialize();
puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ); //PUSTYLE_DEFAULT
puSetDefaultColourScheme (0.8, 0.8, 0.9, 1);
// Initialize PUI
#ifndef PU_USE_NONE
puInit();
#endif
puSetDefaultStyle ( PUSTYLE_SMALL_SHADED ); //PUSTYLE_DEFAULT
puSetDefaultColourScheme (0.8, 0.8, 0.9, 1);
FGFontCache *fc = globals->get_fontcache();
puFont *GuiFont
= fc->get(globals->get_locale()->getStringValue("font",
"typewriter.txf"),
15);
puSetDefaultFonts(*GuiFont, *GuiFont);
guiFnt = puGetDefaultLabelFont();
FGFontCache *fc = globals->get_fontcache();
puFont *GuiFont = fc->get(globals->get_locale()->getStringValue("font", "typewriter.txf"), 15);
puSetDefaultFonts(*GuiFont, *GuiFont);
guiFnt = puGetDefaultLabelFont();
LayoutWidget::setDefaultFont(GuiFont, 15);
LayoutWidget::setDefaultFont(GuiFont, 15);
if (!fgHasNode("/sim/startup/mouse-pointer")) {
// no preference specified for mouse pointer, attempt to autodetect...
// Determine if we need to render the cursor, or if the windowing
// system will do it. First test if we are rendering with glide.
if ( strstr ( general.get_glRenderer(), "Glide" ) ) {
// Test for the MESA_GLX_FX env variable
if ( (mesa_win_state = getenv( "MESA_GLX_FX" )) != NULL) {
// test if we are fullscreen mesa/glide
if ( (mesa_win_state[0] == 'f') ||
(mesa_win_state[0] == 'F') ) {
puShowCursor ();
if (!fgHasNode("/sim/startup/mouse-pointer")) {
// no preference specified for mouse pointer, attempt to autodetect...
// Determine if we need to render the cursor, or if the windowing
// system will do it. First test if we are rendering with
// glide.
// XXX Not bloody likely in 2008...
if ( strstr ( general.get_glRenderer(), "Glide" ) ) {
// Test for the MESA_GLX_FX env variable
char *mesa_win_state = getenv( "MESA_GLX_FX" );
if (mesa_win_state != NULL) {
// test if we are fullscreen mesa/glide
if ( (mesa_win_state[0] == 'f') ||
(mesa_win_state[0] == 'F') ) {
puShowCursor ();
}
}
}
} else if ( !fgGetBool("/sim/startup/mouse-pointer") ) {
// don't show pointer
} else {
// force showing pointer
puShowCursor();
}
// mouse_active = ~mouse_active;
} else if ( !fgGetBool("/sim/startup/mouse-pointer") ) {
// don't show pointer
} else {
// force showing pointer
puShowCursor();
// mouse_active = ~mouse_active;
}
// MOUSE_VIEW mode stuff
initMouseQuat();
};
ref_ptr<GUIInitOperation> initOp;
}
void guiStartInit()
{
initOp = new GUIInitOperation;
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
GraphicsContext* gc = wsa->getGUIGraphicsContext();
gc->add(initOp.get());
}
bool guiFinishInit()
{
if (!initOp.valid())
return false;
if (!initOp->isFinished())
return false;
initMouseQuat();
initOp = 0;
return true;
}

View file

@ -41,7 +41,8 @@
// gui.cxx
extern void guiInit();
extern void guiStartInit();
extern bool guiFinishInit();
extern void mkDialog(const char *txt);
extern void guiErrorMessage(const char *txt);
extern void guiErrorMessage(const char *txt, const sg_throwable &throwable);

View file

@ -1,12 +1,6 @@
/* Special single config.h for MSVC8 build */
#define ENABLE_OSGVIEWER
#define PU_USE_NATIVE
#define ENABLE_OSGVIEWER
#define PU_USE_NATIVE
/* Define to enable plib joystick support */
#ifndef ENABLE_PLIB_JOYSTICK
#define ENABLE_PLIB_JOYSTICK

View file

@ -1,9 +1,6 @@
/* Special single config.h for MSVC6 build - Geoff McLane - 23 July, 2003 */
#define ENABLE_OSGVIEWER
#define PU_USE_NATIVE
/* Define to enable plib joystick support */
#ifndef ENABLE_PLIB_JOYSTICK
#define ENABLE_PLIB_JOYSTICK

View file

@ -327,8 +327,6 @@ FGInput::doMouseClick (int b, int updown, int x, int y, bool mainWindow, const o
}
if (mode.pass_through) {
// 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 (0 <= x && 0 <= y && (globals->get_current_panel() != 0) &&

View file

@ -62,6 +62,7 @@ libMain_a_SOURCES = \
viewmgr.cxx viewmgr.hxx \
FGManipulator.cxx FGManipulator.hxx \
ViewPartitionNode.cxx ViewPartitionNode.hxx \
WindowSystemAdapter.hxx WindowSystemAdapter.cxx \
$(GFX_CODE)
fgfs_SOURCES = bootstrap.cxx

View file

@ -0,0 +1,118 @@
// Copyright (C) 2008 Tim Moore
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <plib/pu.h>
#include<algorithm>
#include <functional>
#include "WindowSystemAdapter.hxx"
using namespace osg;
using namespace std;
using namespace flightgear;
ref_ptr<WindowSystemAdapter> WindowSystemAdapter::_wsa;
void GraphicsContextOperation::operator()(GraphicsContext* gc)
{
run(gc);
++done;
}
WindowSystemAdapter::WindowSystemAdapter() :
_nextWindowID(0), _nextCameraID(0), _isPuInitialized(false)
{
}
GraphicsWindow*
WindowSystemAdapter::registerWindow(GraphicsContext* gc,
const string& windowName)
{
GraphicsWindow* window = new GraphicsWindow(gc, windowName,
_nextWindowID++);
windows.push_back(window);
return window;
}
Camera3D*
WindowSystemAdapter::registerCamera3D(GraphicsWindow* gw, Camera* camera,
const string& cameraName)
{
Camera3D* camera3D = new Camera3D(gw, camera, cameraName);
cameras.push_back(camera3D);
return camera3D;
}
GraphicsWindow*
WindowSystemAdapter::getGUIWindow()
{
WindowVector::const_iterator contextIter
= std::find_if(windows.begin(), windows.end(),
FlagTester<GraphicsWindow>(GraphicsWindow::GUI));
if (contextIter == windows.end())
return 0;
else
return contextIter->get();
}
int
WindowSystemAdapter::getGUIWindowID()
{
const GraphicsWindow* gw = getGUIWindow();
if (!gw)
return -1;
else
return gw->id;
}
GraphicsContext*
WindowSystemAdapter::getGUIGraphicsContext()
{
GraphicsWindow* gw = getGUIWindow();
if (!gw)
return 0;
else
return gw->gc.get();
}
int WindowSystemAdapter::puGetWindow()
{
WindowSystemAdapter* wsa = getWSA();
return wsa->getGUIWindowID();
}
void WindowSystemAdapter::puGetWindowSize(int* width, int* height)
{
// XXX This will have to be different when multiple cameras share
// a single window.
WindowSystemAdapter* wsa = getWSA();
const GraphicsContext* gc = wsa->getGUIGraphicsContext();
const GraphicsContext::Traits *traits = gc->getTraits();
*width = traits->width;
*height = traits->height;
}
bool WindowSystemAdapter::puInitialize()
{
puSetWindowFuncs(puGetWindow, 0, puGetWindowSize, 0);
puRealInit();
}

View file

@ -0,0 +1,150 @@
// Copyright (C) 2008 Tim Moore
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef FLIGHTGEAR_WINDOWSYSTEMADAPTER_HXX
#define FLIGHTGEAR_WINDOWSYSTEMADAPTER_HXX 1
#include <functional>
#include <string>
#include <osg/Referenced>
#include <osg/Camera>
#include <osg/GraphicsContext>
#include <osg/GraphicsThread>
#include <simgear/structure/SGAtomic.hxx>
// Flexible Camera and window support
namespace flightgear
{
/** A window opened by default or via rendering properties
*/
class GraphicsWindow : public osg::Referenced
{
public:
GraphicsWindow(osg::GraphicsContext* gc_, const std::string& name_,
int id_, unsigned flags_ = 0) :
gc(gc_), name(name_), id(id_), flags(flags_)
{
}
/** The OSG graphics context for this window.
*/
osg::ref_ptr<osg::GraphicsContext> gc;
/** The window's internal name.
*/
std::string name;
enum Flags {
/** The GUI (and 2D cockpit) will be drawn on this window.
*/
GUI = 1
};
int id;
unsigned flags;
};
/** Camera associated with a 3d view. The camera might occupy an
* entire window or share one with other cameras.
*/
class Camera3D : public osg::Referenced
{
public:
Camera3D(GraphicsWindow* window_, osg::Camera* camera_, const std::string& name_,
unsigned flags_ = 0) :
window(window_), camera(camera_), name(name_), flags(flags_)
{
}
osg::ref_ptr<GraphicsWindow> window;
osg::ref_ptr<osg::Camera> camera;
std::string name;
enum Flags {
SHARES_WINDOW = 1, /**< Camera shares window with other cameras*/
MASTER = 2 /**< Camera has same view as master camera*/
};
unsigned flags;
};
typedef std::vector<osg::ref_ptr<GraphicsWindow> > WindowVector;
typedef std::vector<osg::ref_ptr<Camera3D> > Camera3DVector;
/**
* An operation that is run once with a particular GraphicsContext
* current.
*/
class GraphicsContextOperation : public osg::GraphicsOperation
{
public:
GraphicsContextOperation(const std::string& name) :
osg::GraphicsOperation(name, false)
{
}
virtual void operator()(osg::GraphicsContext* gc);
virtual void run(osg::GraphicsContext* gc) = 0;
bool isFinished() const { return done != 0; }
private:
SGAtomic done;
};
/** Adapter from windows system / graphics context management API to
* functions used by flightgear. This papers over the difference
* between osgViewer Viewer, which handles multiple windows, graphics
* threads, etc., and the embedded viewer used with GLUT and SDL.
*/
class WindowSystemAdapter : public osg::Referenced
{
public:
WindowSystemAdapter();
virtual ~WindowSystemAdapter() {}
WindowVector windows;
Camera3DVector cameras;
GraphicsWindow* registerWindow(osg::GraphicsContext* gc,
const std::string& windowName);
Camera3D* registerCamera3D(GraphicsWindow* gw, osg::Camera* camera,
const std::string& cameraName);
GraphicsWindow* getGUIWindow();
int getGUIWindowID();
osg::GraphicsContext* getGUIGraphicsContext();
/** Initialize the plib pui interface library. This might happen
*in another thread and may be deferred.
*/
virtual bool puInitialize();
/** Returns true if pui initialization has finished.
*/
template<typename T>
class FlagTester : public std::unary_function<osg::ref_ptr<T>, bool>
{
public:
FlagTester(unsigned flags_) : flags(flags_) {}
bool operator() (const osg::ref_ptr<T>& obj)
{
return (obj->flags & flags) != 0;
}
unsigned flags;
};
static WindowSystemAdapter* getWSA() { return _wsa.get(); }
static void setWSA(WindowSystemAdapter* wsa) { _wsa = wsa; }
protected:
int _nextWindowID;
int _nextCameraID;
osg::ref_ptr<GraphicsContextOperation> _puInitOp;
bool _isPuInitialized;
static osg::ref_ptr<WindowSystemAdapter> _wsa;
// Default callbacks for plib
static int puGetWindow();
static void puGetWindowSize(int* width, int* height);
};
}
#endif

View file

@ -21,6 +21,9 @@
#include "globals.hxx"
#include "renderer.hxx"
#include "fg_props.hxx"
#include "WindowSystemAdapter.hxx"
using namespace flightgear;
//
// Native glut callbacks.
@ -153,6 +156,7 @@ static void GLUTreshape(int w, int h)
void fgOSInit(int* argc, char** argv)
{
glutInit(argc, argv);
WindowSystemAdapter::setWSA(new WindowSystemAdapter);
}
void fgOSFullScreen()
@ -216,10 +220,16 @@ static unsigned int getOSGModifiers(int glutModifiers)
return result;
}
void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
bool stencil, bool fullscreen)
void fgOSOpenWindow(bool stencil)
{
int w = fgGetInt("/sim/startup/xsize");
int h = fgGetInt("/sim/startup/ysize");
int bpp = fgGetInt("/sim/rendering/bits-per-pixel");
bool alpha = fgGetBool("/sim/rendering/clouds3d-enable");
bool fullscreen = fgGetBool("/sim/startup/fullscreen");
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
int mode = GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE;
if(alpha) mode |= GLUT_ALPHA;
if(stencil && bpp > 16) mode |= GLUT_STENCIL;
@ -256,18 +266,21 @@ void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
int realh = h;
viewer = new osgViewer::Viewer;
gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh);
GraphicsWindow* window = wsa->registerWindow(gw.get(), string("main"));
window->flags |= GraphicsWindow::GUI;
viewer->setDatabasePager(FGScenery::getPagerSingleton());
// now the main camera ...
//osg::ref_ptr<osg::Camera> camera = new osg::Camera;
osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
osg::Camera* camera = new osg::Camera;
mainCamera = camera;
osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
// 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, realw, realh));
camera->setProjectionResizePolicy(rsp);
//viewer->addSlave(camera.get());
camera->setProjectionResizePolicy(osg::Camera::FIXED);
Camera3D* cam3D = wsa->registerCamera3D(window, camera, string("main"));
cam3D->flags |= Camera3D::MASTER;
// Add as a slave for compatibility with the non-embedded osgViewer.
viewer->addSlave(camera);
viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
// Let FG handle the escape key with a confirmation
viewer->setKeyEventSetsDone(0);
@ -280,11 +293,6 @@ void fgOSOpenWindow(int w, int h, int bpp, bool alpha,
globals->get_renderer()->setViewer(viewer.get());
}
// Noop; the graphics context is always current
void fgMakeCurrent()
{
}
bool fgOSIsMainCamera(const osg::Camera*)
{
return true;
@ -294,3 +302,8 @@ bool fgOSIsMainContext(const osg::GraphicsContext*)
{
return true;
}
osg::GraphicsContext* fgOSGetMainContext()
{
return gw.get();
}

View file

@ -1,13 +1,17 @@
#ifndef _FG_OS_HXX
#define _FG_OS_HXX
// Plib pui needs to know at compile time what toolkit is in use.
// Change this when we move to something other than glut.
// #define PU_USE_GLUT -- moved to configure.ac -- EMH
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string>
#include <vector>
#include <osg/ref_ptr>
#include <osg/Camera>
#include <osg/GraphicsContext>
enum { MOUSE_BUTTON_LEFT,
MOUSE_BUTTON_MIDDLE,
@ -45,8 +49,7 @@ enum { KEYMOD_NONE = 0,
//
void fgOSInit(int* argc, char** argv);
void fgOSOpenWindow(int w, int h, int bpp, bool alpha, bool stencil,
bool fullscreen);
void fgOSOpenWindow(bool stencil);
void fgOSFullScreen();
void fgOSMainLoop();
void fgOSExit(int code);
@ -82,9 +85,17 @@ void fgRegisterKeyHandler(fgKeyHandler func);
void fgRegisterMouseClickHandler(fgMouseClickHandler func);
void fgRegisterMouseMotionHandler(fgMouseMotionHandler func);
void fgMakeCurrent();
bool fgOSIsMainCamera(const osg::Camera* camera);
bool fgOSIsMainContext(const osg::GraphicsContext* context);
/** Get graphics context of the main camera. This is the principal
* window in multi-window configurations, or the only window in an
* embedded configuration. The GUI will be added to this context.
*/
osg::GraphicsContext* fgOSGetMainContext();
#endif // _FG_OS_HXX

View file

@ -17,6 +17,10 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <config.h>
#include <plib/pu.h>
#include <osg/GraphicsContext>
#include "fg_os.hxx"
#include "globals.hxx"
#include "renderer.hxx"
@ -60,3 +64,5 @@ void fgRegisterMouseMotionHandler(fgMouseMotionHandler func)
void fgRequestRedraw()
{
}

View file

@ -22,6 +22,11 @@
# include <config.h>
#endif
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <stdlib.h>
#include <simgear/compiler.h>
@ -45,6 +50,7 @@
#include "util.hxx"
#include "globals.hxx"
#include "renderer.hxx"
#include "WindowSystemAdapter.hxx"
#if (FG_OSG_VERSION >= 19008)
#define OSG_HAS_MOUSE_CURSOR_PATCH
@ -57,8 +63,12 @@
// fg_os implementation
//
using namespace std;
using namespace flightgear;
using namespace osg;
static osg::ref_ptr<osgViewer::Viewer> viewer;
static osg::ref_ptr<osg::Camera> mainCamera;
@ -67,59 +77,24 @@ static osg::ref_ptr<osg::Camera> mainCamera;
namespace
{
struct fgResizeCallback : public GraphicsContext::ResizedCallback
// silly function for making the default window and camera names
std::string makeName(const string& prefix, int num)
{
fgResizeCallback(Camera* slaveCamera)
: mainSlaveCamera(slaveCamera)
{}
virtual void resizedImplementation(GraphicsContext* gc, int x, int y,
int width, int height);
ref_ptr<Camera> mainSlaveCamera;
};
void fgResizeCallback::resizedImplementation(GraphicsContext* gc,
int x, int y,
int width, int height)
{
View* view = mainSlaveCamera->getView();
View::Slave* slave = (view ?
view->findSlaveForCamera(mainSlaveCamera.get()) : 0);
if (slave) {
Matrixd projOffset(slave->_projectionOffset);
gc->resizedImplementation(x, y, width, height);
// Restore projection offsets changed by
// GraphicsContext::resizedImplementation
slave->_projectionOffset = projOffset;
} else {
gc->resizedImplementation(x, y, width, height);
}
std::stringstream stream;
stream << prefix << num;
return stream.str();
}
}
void fgOSOpenWindow(int w, int h, int bpp,
bool alpha, bool stencil, bool fullscreen)
GraphicsContext::Traits*
makeDefaultTraits(GraphicsContext::WindowingSystemInterface* wsi, bool stencil)
{
osg::GraphicsContext::WindowingSystemInterface* wsi;
wsi = osg::GraphicsContext::getWindowingSystemInterface();
int w = fgGetInt("/sim/startup/xsize");
int h = fgGetInt("/sim/startup/ysize");
int bpp = fgGetInt("/sim/rendering/bits-per-pixel");
bool alpha = fgGetBool("/sim/rendering/clouds3d-enable");
bool fullscreen = fgGetBool("/sim/startup/fullscreen");
viewer = new osgViewer::Viewer;
viewer->setDatabasePager(FGScenery::getPagerSingleton());
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;
GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits;
traits->readDISPLAY();
int cbits = (bpp <= 16) ? 5 : 8;
int zbits = (bpp <= 16) ? 16 : 24;
@ -132,10 +107,10 @@ void fgOSOpenWindow(int w, int h, int bpp,
traits->doubleBuffer = true;
traits->mipMapGeneration = true;
traits->windowName = "FlightGear";
// XXX should check per window too.
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;
@ -156,96 +131,166 @@ void fgOSOpenWindow(int w, int h, int bpp,
#endif
traits->supportsResize = true;
}
return traits;
}
osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
void setTraitsFromProperties(GraphicsContext::Traits* traits,
const SGPropertyNode* winNode,
GraphicsContext::WindowingSystemInterface* wsi)
{
traits->hostName
= winNode->getStringValue("host-name", traits->hostName.c_str());
traits->displayNum = winNode->getIntValue("display", traits->displayNum);
traits->screenNum = winNode->getIntValue("screen", traits->screenNum);
if (winNode->getBoolValue("fullscreen",
fgGetBool("/sim/startup/fullscreen"))) {
unsigned width = 0;
unsigned height = 0;
wsi->getScreenResolution(*traits, width, height);
traits->windowDecoration = false;
traits->width = width;
traits->height = height;
traits->supportsResize = false;
} else {
traits->windowDecoration = winNode->getBoolValue("decoration", true);
traits->width = winNode->getIntValue("width", traits->width);
traits->height = winNode->getIntValue("height", traits->height);
traits->supportsResize = true;
}
traits->x = winNode->getIntValue("x", traits->x);
traits->y = winNode->getIntValue("y", traits->y);
if (winNode->hasChild("window-name"))
traits->windowName = winNode->getStringValue("window-name");
else if (winNode->hasChild("name"))
traits->windowName = winNode->getStringValue("name");
}
} //namespace
void fgOSOpenWindow(bool stencil)
{
osg::GraphicsContext::WindowingSystemInterface* wsi;
wsi = osg::GraphicsContext::getWindowingSystemInterface();
viewer = new osgViewer::Viewer;
viewer->setDatabasePager(FGScenery::getPagerSingleton());
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
= makeDefaultTraits(wsi, stencil);
// 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.
FGManipulator* manipulator = globals->get_renderer()->getManipulator();
int nCameras = 0;
string defaultName("slave");
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
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;
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);
// 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);
setTraitsFromProperties(cameraTraits.get(), cameraNode, wsi);
// 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;
double shearx = cameraNode->getDoubleValue("shear-x", 0);
double sheary = cameraNode->getDoubleValue("shear-y", 0);
cameraTraits->hostName
= cameraNode->getStringValue("host-name", traits->hostName.c_str());
cameraTraits->displayNum
= cameraNode->getIntValue("display", traits->displayNum);
cameraTraits->screenNum
= cameraNode->getIntValue("screen", traits->screenNum);
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;
// ok found a camera configuration, add a new slave if possible
GraphicsContext* gc
= GraphicsContext::createGraphicsContext(cameraTraits.get());
if (gc) {
gc->realize();
Camera *camera = new Camera;
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 Viewport(0, 0, cameraTraits->width,
cameraTraits->height));
const char* cameraName = cameraNode->getStringValue("name");
string cameraNameString = (cameraName ? string(cameraName)
: makeName(defaultName, i));
GraphicsWindow* window = wsa->registerWindow(gc,
cameraNameString);
Camera3D* cam3D = wsa->registerCamera3D(window, camera,
cameraNameString);
if (shearx == 0 && sheary == 0)
cam3D->flags |= Camera3D::MASTER;
viewer->addSlave(camera, Matrix::translate(-shearx, -sheary, 0),
Matrix());
} else {
SG_LOG(SG_GENERAL, SG_WARN,
"Couldn't create graphics context on "
<< cameraTraits->hostName << ":"
<< cameraTraits->displayNum
<< "." << cameraTraits->screenNum);
}
}
// 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());
if( gc != NULL ) {
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());
nCameras++;
}
}
if (nCameras > 1)
manipulator->setResizable(false);
}
// 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.
camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
camera->setProjectionResizePolicy(rsp);
if (nCameras == 0) {
// Only one principal camera
gc->setResizedCallback(new fgResizeCallback(camera.get()));
// XXX mainCamera's purpose is to establish a "main graphics
// context" that can be made current (if necessary). But that
// should be a context established with a window. It's used to
// choose whether to render the GUI and panel camera nodes, but
// that's obsolete because the GUI is rendered in its own
// slave. And it's used to translate mouse event coordinates, but
// that's bogus because mouse clicks should work on any camera. In
// short, mainCamera must die :)
Camera3DVector::iterator citr
= find_if(wsa->cameras.begin(), wsa->cameras.end(),
WindowSystemAdapter::FlagTester<Camera3D>(Camera3D::MASTER));
if (citr == wsa->cameras.end()) {
// Create a camera aligned with the master camera. Eventually
// this will be optional.
Camera* camera = new osg::Camera;
mainCamera = camera;
osg::GraphicsContext* 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.
camera->setViewport(new osg::Viewport(0, 0,
traits->width, traits->height));
GraphicsWindow* window = wsa->registerWindow(gc, string("main"));
window->flags |= GraphicsWindow::GUI;
Camera3D* camera3d = wsa->registerCamera3D(window, camera,
string("main"));
camera3d->flags |= Camera3D::MASTER;
// Why a slave? It seems to be the easiest way to assign cameras,
// for which we've created the graphics context ourselves, to
// the viewer.
viewer->addSlave(camera);
} else {
mainCamera = (*citr)->camera;
}
// Why a slave? It seems to be the easiest way to assign cameras,
// for which we've created the graphics context ourselves, to the viewer.
viewer->addSlave(camera.get());
viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
if (wsa->cameras.size() != 1) {
manipulator->setResizable(false);
}
viewer->getCamera()->setProjectionResizePolicy(osg::Camera::FIXED);
viewer->setCameraManipulator(manipulator);
// Let FG handle the escape key with a confirmation
viewer->setKeyEventSetsDone(0);
// The viewer won't start without some root.
@ -288,9 +333,9 @@ void fgWarpMouse(int x, int y)
1.0f - 2.0f * (float)y / ysize);
}
// Noop
void fgOSInit(int* argc, char** argv)
{
WindowSystemAdapter::setWSA(new WindowSystemAdapter);
}
// Noop
@ -345,16 +390,6 @@ int fgGetMouseCursor()
return _cursor;
}
void fgMakeCurrent()
{
if (!mainCamera.valid())
return;
osg::GraphicsContext* gc = mainCamera->getGraphicsContext();
if (!gc)
return;
gc->makeCurrent();
}
bool fgOSIsMainContext(const osg::GraphicsContext* context)
{
if (!mainCamera.valid())
@ -374,3 +409,16 @@ bool fgOSIsMainCamera(const osg::Camera* camera)
return true;
return false;
}
GraphicsContext* fgOSGetMainContext()
{
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
WindowVector::iterator contextIter
= std::find_if(wsa->windows.begin(), wsa->windows.end(),
WindowSystemAdapter::FlagTester<GraphicsWindow>(GraphicsWindow::GUI));
if (contextIter == wsa->windows.end())
return 0;
else
return (*contextIter)->gc.get();
}

View file

@ -8,12 +8,15 @@
#include <simgear/debug/logstream.hxx>
#include <SDL/SDL.h>
#include <plib/pu.h>
#include <Scenery/scenery.hxx>
#include "fg_os.hxx"
#include "globals.hxx"
#include "renderer.hxx"
#include "fg_props.hxx"
#include "WindowSystemAdapter.hxx"
using namespace flightgear;
//
// fg_os callback registration APIs
@ -34,11 +37,16 @@ static osg::ref_ptr<osgViewer::Viewer> viewer;
static osg::ref_ptr<osg::Camera> mainCamera;
static osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw;
void fgOSOpenWindow(int w, int h, int bpp,
bool alpha, bool stencil, bool fullscreen)
void fgOSOpenWindow(bool stencil)
{
int w = fgGetInt("/sim/startup/xsize");
int h = fgGetInt("/sim/startup/ysize");
int bpp = fgGetInt("/sim/rendering/bits-per-pixel");
bool alpha = fgGetBool("/sim/rendering/clouds3d-enable");
bool fullscreen = fgGetBool("/sim/startup/fullscreen");
int cbits = (bpp <= 16) ? 5 : 8;
int zbits = (bpp <= 16) ? 16 : 24;
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE) == -1)
throw sg_throwable(string("Failed to initialize SDL: ")
@ -84,17 +92,20 @@ void fgOSOpenWindow(int w, int h, int bpp,
viewer = new osgViewer::Viewer;
viewer->setDatabasePager(FGScenery::getPagerSingleton());
gw = viewer->setUpViewerAsEmbeddedInWindow(0, 0, realw, realh);
GraphicsWindow* window = wsa->registerWindow(gw.get(), string("main"));
window->flags |= GraphicsWindow::GUI;
// now the main camera ...
//osg::ref_ptr<osg::Camera> camera = new osg::Camera;
osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
osg::Camera* camera = new osg::Camera;
mainCamera = camera;
osg::Camera::ProjectionResizePolicy rsp = osg::Camera::VERTICAL;
// 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, realw, realh));
camera->setProjectionResizePolicy(rsp);
//viewer->addSlave(camera.get());
camera->setProjectionResizePolicy(osg::Camera::FIXED);
Camera3D* cam3D = wsa->registerCamera3D(window, camera, string("main"));
cam3D->flags |= Camera3D::MASTER;
// Add as a slave for compatibility with the non-embedded osgViewer.
viewer->addSlave(camera);
viewer->setCameraManipulator(globals->get_renderer()->getManipulator());
// Let FG handle the escape key with a confirmation
viewer->setKeyEventSetsDone(0);
@ -265,7 +276,7 @@ void fgWarpMouse(int x, int y)
void fgOSInit(int* argc, char** argv)
{
// Nothing to do here. SDL has no command line options.
WindowSystemAdapter::setWSA(new WindowSystemAdapter);
}
void fgOSFullScreen()
@ -281,7 +292,7 @@ static struct cursor_rec {
int h;
int hotx;
int hoty;
char *img[32]; // '.' == white, '#' == black, ' ' == transparent
const char *img[32]; // '.' == white, '#' == black, ' ' == transparent
} cursors[] = {
{ MOUSE_CURSOR_POINTER, 0, // must be first!
10, 16, 1, 1,
@ -400,11 +411,6 @@ static void initCursors()
}
}
// Noop; the graphics context is always current
void fgMakeCurrent()
{
}
bool fgOSIsMainCamera(const osg::Camera*)
{
return true;
@ -414,3 +420,8 @@ bool fgOSIsMainContext(const osg::GraphicsContext*)
{
return true;
}
osg::GraphicsContext* fgOSGetMainContext()
{
return gw.get();
}

View file

@ -679,9 +679,6 @@ 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++;
@ -703,10 +700,12 @@ static void fgIdleFunction ( void ) {
SG_LOG ( SG_GENERAL, SG_INFO, "Depth buffer bits = " << tmp );
// Initialize the user interface so that we can use fonts
guiInit();
guiStartInit();
} else if ( idle_state == 1 ) {
if (!guiFinishInit())
return;
idle_state++;
fgSplashProgress("reading aircraft list");
@ -715,23 +714,6 @@ static void fgIdleFunction ( void ) {
idle_state++;
// Read the list of available aircraft
fgReadAircraft();
// get the address of our OpenGL extensions
// if (SGIsOpenGLExtensionSupported("GL_EXT_point_parameters") ) {
// glPointParameterIsSupported = true;
// glPointParameterfPtr = (glPointParameterfProc)
// SGLookupFunction("glPointParameterfEXT");
// glPointParameterfvPtr = (glPointParameterfvProc)
// SGLookupFunction("glPointParameterfvEXT");
// } else if ( SGIsOpenGLExtensionSupported("GL_ARB_point_parameters") ) {
// glPointParameterIsSupported = true;
// glPointParameterfPtr = (glPointParameterfProc)
// SGLookupFunction("glPointParameterfARB");
// glPointParameterfvPtr = (glPointParameterfvProc)
// SGLookupFunction("glPointParameterfvARB");
// } else {
// glPointParameterIsSupported = false;
// }
fgSplashProgress("reading airport & navigation data");
@ -1060,12 +1042,7 @@ bool fgMainInit( int argc, char **argv ) {
// Clouds3D requires an alpha channel
// clouds may require stencil buffer
fgOSOpenWindow( fgGetInt("/sim/startup/xsize"),
fgGetInt("/sim/startup/ysize"),
fgGetInt("/sim/rendering/bits-per-pixel"),
fgGetBool("/sim/rendering/clouds3d-enable"),
get_stencil_buffer,
fgGetBool("/sim/startup/fullscreen") );
fgOSOpenWindow(get_stencil_buffer);
// Initialize the splash screen right away
fntInit();

View file

@ -18,9 +18,6 @@
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#ifdef HAVE_CONFIG_H
# include <config.h>
@ -162,11 +159,6 @@ public:
{
if (!fgOSIsMainContext(state.getGraphicsContext()))
return;
state.pushStateSet(getStateSet());
state.apply();
state.setActiveTextureUnit(0);
state.setClientActiveTextureUnit(0);
state.disableAllVertexArrays();
glPushAttrib(GL_ALL_ATTRIB_BITS);
@ -176,11 +168,6 @@ public:
glPopClientAttrib();
glPopAttrib();
state.popStateSet();
state.dirtyAllModes();
state.dirtyAllAttributes();
state.dirtyAllVertexArrays();
}
virtual osg::Object* cloneType() const { return new SGPuDrawable; }
@ -212,14 +199,9 @@ public:
{ drawImplementation(*renderInfo.getState()); }
void drawImplementation(osg::State& state) const
{
// std::cout << state.getGraphicsContext() << std::endl;
if (!fgOSIsMainContext(state.getGraphicsContext()))
return;
state.pushStateSet(getStateSet());
state.apply();
state.setActiveTextureUnit(0);
state.setClientActiveTextureUnit(0);
state.disableAllVertexArrays();
glPushAttrib(GL_ALL_ATTRIB_BITS);
@ -240,11 +222,6 @@ public:
glPopClientAttrib();
glPopAttrib();
state.popStateSet();
state.dirtyAllModes();
state.dirtyAllAttributes();
state.dirtyAllVertexArrays();
}
virtual osg::Object* cloneType() const { return new SGHUDAndPanelDrawable; }
@ -428,12 +405,41 @@ FGRenderer::splashinit( void ) {
#endif
}
namespace
{
// Create a slave camera that will be used to render a fixed GUI-like
// element.
osg::Camera*
makeSlaveCamera(osg::Camera::RenderOrder renderOrder, int orderNum)
{
using namespace osg;
Camera* camera = new osg::Camera;
GraphicsContext *gc = fgOSGetMainContext();
camera->setRenderOrder(renderOrder, orderNum);
camera->setClearMask(0);
camera->setInheritanceMask(CullSettings::ALL_VARIABLES
& ~(CullSettings::COMPUTE_NEAR_FAR_MODE
| CullSettings::CULLING_MODE));
camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
camera->setCullingMode(osg::CullSettings::NO_CULLING);
camera->setGraphicsContext(gc);
// Establish an initial viewport. This may be altered,
// particularly when drawing a 2d panel.
const GraphicsContext::Traits *traits = gc->getTraits();
camera->setViewport(new Viewport(0, 0, traits->width, traits->height));
camera->setProjectionResizePolicy(Camera::FIXED);
camera->setReferenceFrame(Transform::ABSOLUTE_RF);
camera->setAllowEventFocus(false);
globals->get_renderer()->getViewer()->addSlave(camera, false);
return camera;
}
}
void
FGRenderer::init( void ) {
// The viewer can call this before the graphics context is current
// in the main thread; indeed, in a multithreaded setup it might
// never be current in the main thread.
fgMakeCurrent();
FGRenderer::init( void )
{
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
osg::initNotifyLevel();
@ -534,15 +540,8 @@ FGRenderer::init( void ) {
stateSet->setUpdateCallback(new FGFogEnableUpdateCallback);
// plug in the GUI
osg::Camera* guiCamera = new osg::Camera;
guiCamera->setRenderOrder(osg::Camera::POST_RENDER, 100);
guiCamera->setClearMask(0);
GLbitfield inheritanceMask = osg::CullSettings::ALL_VARIABLES;
inheritanceMask &= ~osg::CullSettings::COMPUTE_NEAR_FAR_MODE;
inheritanceMask &= ~osg::CullSettings::CULLING_MODE;
guiCamera->setInheritanceMask(inheritanceMask);
guiCamera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
guiCamera->setCullingMode(osg::CullSettings::NO_CULLING);
osg::Camera* guiCamera = makeSlaveCamera(osg::Camera::POST_RENDER, 100);
guiCamera->setName("GUI");
osg::Geode* geode = new osg::Geode;
geode->addDrawable(new SGPuDrawable);
geode->addDrawable(new SGHUDAndPanelDrawable);