#include <osg/Matrixd>
#include <osg/Viewport>
#include <osg/Version>
+#include <osg/View>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/Viewer>
#include <osgGA/MatrixManipulator>
// fg_os implementation
//
+using namespace osg;
+
static osg::ref_ptr<osgViewer::Viewer> viewer;
static osg::ref_ptr<osg::Camera> 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<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);
+ }
+
+}
+
+}
void fgOSOpenWindow(int w, int h, int bpp,
bool alpha, bool stencil, bool fullscreen)
{
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")
// 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());
- 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;
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(),
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;
- osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
- viewer->getCamera()->setProjectionMatrixAsPerspective(fov_height, 4.0/3.0,
- fov_near, fov_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;
+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);
+
}
-
bool
FGRenderer::pick( unsigned x, unsigned y,
std::vector<SGSceneryPick>& pickList,
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,