1
0
Fork 0

Fix main window aspect ratios other than 4/3

This also fixes distortion weirdness in the osgviewer version. That
was caused by osg::GraphicsContext getting in the act on resize events
and adding its own scaling to the projectionOffset of slave cameras!
This commit is contained in:
timoore 2008-01-25 18:44:45 +00:00
parent 00f8463ab4
commit b47157041e
3 changed files with 62 additions and 52 deletions

View file

@ -33,6 +33,7 @@
#include <osg/Matrixd>
#include <osg/Viewport>
#include <osg/Version>
#include <osg/View>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/Viewer>
#include <osgGA/MatrixManipulator>
@ -56,9 +57,47 @@
// 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)
{
@ -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());

View file

@ -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<SGSceneryPick>& pickList,

View file

@ -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,