diff --git a/src/Main/fg_os_osgviewer.cxx b/src/Main/fg_os_osgviewer.cxx index 63bb3e41e..087d29757 100644 --- a/src/Main/fg_os_osgviewer.cxx +++ b/src/Main/fg_os_osgviewer.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -56,9 +57,47 @@ // fg_os implementation // +using namespace osg; + static osg::ref_ptr viewer; static osg::ref_ptr mainCamera; +// Callback to prevent the GraphicsContext resized function from messing +// with the projection matrix of the slave + +namespace +{ +struct fgResizeCallback : public GraphicsContext::ResizedCallback +{ + fgResizeCallback(Camera* slaveCamera) + : mainSlaveCamera(slaveCamera) + {} + + virtual void resizedImplementation(GraphicsContext* gc, int x, int y, + int width, int height); + ref_ptr 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); + } + +} + +} void fgOSOpenWindow(int w, int h, int bpp, bool alpha, bool stencil, bool fullscreen) { @@ -67,7 +106,6 @@ void fgOSOpenWindow(int w, int h, int bpp, viewer = new osgViewer::Viewer; viewer->setDatabasePager(FGScenery::getPagerSingleton()); - // Avoid complications with fg's custom drawables. std::string mode; mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded"); if (mode == "AutomaticSelection") @@ -196,6 +234,12 @@ void fgOSOpenWindow(int w, int h, int bpp, // 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())); + } + // 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()); diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 40cce615b..41e313c09 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -751,6 +751,9 @@ FGRenderer::update( bool refresh_camera_settings ) { - current__view->getSGLocation()->get_cur_elev_m(); float scene_nearplane, scene_farplane; + // XXX Given that the own airplane model is part of the scene + // graph, should this business be ripped out? The near plane is + // ignored by setCameraParameters. if ( agl > 10.0 ) { scene_nearplane = 10.0f; scene_farplane = 120000.0f; @@ -758,7 +761,9 @@ FGRenderer::update( bool refresh_camera_settings ) { scene_nearplane = groundlevel_nearplane->getDoubleValue(); scene_farplane = 120000.0f; } - setNearFar( scene_nearplane, scene_farplane ); + setCameraParameters(current__view->get_v_fov(), + current__view->get_aspect_ratio(), + scene_nearplane, scene_farplane); // sgEnviro.startOfFrame(current__view->get_view_pos(), // current__view->get_world_up(), @@ -846,50 +851,19 @@ FGRenderer::resize( int width, int height ) { viewmgr->get_view(i)-> set_aspect_ratio((float)view_h / (float)width); } - - setFOV( viewmgr->get_current_view()->get_h_fov(), - viewmgr->get_current_view()->get_v_fov() ); } } - -// we need some static storage space for these values. However, we -// can't store it in a renderer class object because the functions -// that manipulate these are static. They are static so they can -// interface to the display callback system. There's probably a -// better way, there has to be a better way, but I'm not seeing it -// right now. -static float fov_width = 55.0; -static float fov_height = 42.0; -static float fov_near = 1.0; -static float fov_far = 1000.0; - - -/** FlightGear code should use this routine to set the FOV rather than - * calling the ssg routine directly - */ -void FGRenderer::setFOV( float w, float h ) { - fov_width = w; - fov_height = h; +void FGRenderer::setCameraParameters(float vfov, float aspectRatio, + float near, float far) +{ + near = .1; osgViewer::Viewer* viewer = globals->get_renderer()->getViewer(); - viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, - fov_near, fov_far); + viewer->getCamera()->setProjectionMatrixAsPerspective(vfov, + 1.0f / aspectRatio, + near, far); + } - - -/** FlightGear code should use this routine to set the Near/Far clip - * planes rather than calling the ssg routine directly - */ -void FGRenderer::setNearFar( float n, float f ) { -// OSGFIXME: we have currently too much z-buffer fights -n = 0.1; - fov_near = n; - fov_far = f; - osgViewer::Viewer* viewer = globals->get_renderer()->getViewer(); - viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0, - fov_near, fov_far); -} - bool FGRenderer::pick( unsigned x, unsigned y, std::vector& pickList, diff --git a/src/Main/renderer.hxx b/src/Main/renderer.hxx index de21b932e..f651be821 100644 --- a/src/Main/renderer.hxx +++ b/src/Main/renderer.hxx @@ -40,18 +40,10 @@ public: static void update( bool refresh_camera_settings ); inline static void update() { update( true ); } - - /** FlightGear code should use this routine to set the FOV rather - * than calling the ssg routine directly + /** Set all the camera parameters at once. aspectRatio is height / width. */ - static void setFOV( float w, float h ); - - - /** FlightGear code should use this routine to set the Near/Far - * clip planes rather than calling the ssg routine directly - */ - static void setNearFar( float n, float f ); - + static void setCameraParameters(float vfov, float aspectRatio, + float near, float far); /** Just pick into the scene and return the pick callbacks on the way ... */ static bool pick( unsigned x, unsigned y,