From 7443b8b5e8419869e401f95af28cea8eac72450a Mon Sep 17 00:00:00 2001 From: frohlich Date: Mon, 21 May 2007 17:50:02 +0000 Subject: [PATCH] Modified Files: 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. --- configure.ac | 9 +- src/Main/FGManipulator.cxx | 181 +++++++++++++++++++++++++++ src/Main/FGManipulator.hxx | 124 +++++++++++++++++++ src/Main/Makefile.am | 9 +- src/Main/fg_os.cxx | 4 + src/Main/fg_os.hxx | 1 + src/Main/fg_os_osgviewer.cxx | 165 ++++++++++++++++++++++++ src/Main/fg_os_sdl.cxx | 5 + src/Main/main.cxx | 3 + src/Main/renderer.cxx | 234 ++++++++++++++++++++++++----------- src/Main/renderer.hxx | 21 ++++ src/Network/jpg-httpd.cxx | 11 +- 12 files changed, 690 insertions(+), 77 deletions(-) create mode 100644 src/Main/FGManipulator.cxx create mode 100644 src/Main/FGManipulator.hxx create mode 100644 src/Main/fg_os_osgviewer.cxx diff --git a/configure.ac b/configure.ac index 18ecf3a51..9a2b50ea7 100644 --- a/configure.ac +++ b/configure.ac @@ -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 index 000000000..e4a551f5d --- /dev/null +++ b/src/Main/FGManipulator.cxx @@ -0,0 +1,181 @@ +#include + +#include + +#include +#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(&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 index 000000000..dae69d243 --- /dev/null +++ b/src/Main/FGManipulator.hxx @@ -0,0 +1,124 @@ +#ifndef FGMANIPULATOR_H +#define FGMANIPULATOR_H 1 + +#include +#include + +#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 _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 --git a/src/Main/Makefile.am b/src/Main/Makefile.am index f420d7fd1..e9c8e6bec 100644 --- a/src/Main/Makefile.am +++ b/src/Main/Makefile.am @@ -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 \ diff --git a/src/Main/fg_os.cxx b/src/Main/fg_os.cxx index d60f153ef..26767fcc4 100644 --- a/src/Main/fg_os.cxx +++ b/src/Main/fg_os.cxx @@ -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() +{ +} diff --git a/src/Main/fg_os.hxx b/src/Main/fg_os.hxx index 5b5df9c39..931dcb10f 100644 --- a/src/Main/fg_os.hxx +++ b/src/Main/fg_os.hxx @@ -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 index 000000000..120647237 --- /dev/null +++ b/src/Main/fg_os_osgviewer.cxx @@ -0,0 +1,165 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 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 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 --git a/src/Main/fg_os_sdl.cxx b/src/Main/fg_os_sdl.cxx index dcb9c6541..e9ad6f775 100644 --- a/src/Main/fg_os_sdl.cxx +++ b/src/Main/fg_os_sdl.cxx @@ -407,3 +407,8 @@ static void initCursors() cursors[i].hoty); } } + +// Noop; the graphics context is always current +void fgMakeCurrent() +{ +} diff --git a/src/Main/main.cxx b/src/Main/main.cxx index cd5bba53a..ffb8d499b 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -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++; diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index b6a8c6f07..b0ba33414 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -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(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& 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 --git a/src/Main/renderer.hxx b/src/Main/renderer.hxx index 02e0f6982..7bc54bfe9 100644 --- a/src/Main/renderer.hxx +++ b/src/Main/renderer.hxx @@ -6,6 +6,10 @@ #include #include +#include + +#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& 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 viewer; + osg::ref_ptr manipulator; }; #endif diff --git a/src/Network/jpg-httpd.cxx b/src/Network/jpg-httpd.cxx index 0516dd818..9c83d3446 100644 --- a/src/Network/jpg-httpd.cxx +++ b/src/Network/jpg-httpd.cxx @@ -42,6 +42,7 @@ #include
#include
+#include
#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(); -- 2.39.5