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:
parent
00f8463ab4
commit
b47157041e
3 changed files with 62 additions and 52 deletions
|
@ -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());
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue