根据给定的窗口参数来创建一个图形设备
void View::setUpViewInWindow(int x, int y, int width, int height, unsigned int screenNum)
{
apply(new osgViewer::SingleWindow(x, y, width, height, screenNum));
}
参数:窗口左上角坐标x,y,宽度width,高度height,以及屏幕数screenNum
/** single camera on a single window.*/
//在View.h
/** Base class for View configurations for setting up Camera and Windowing.*/
class OSGVIEWER_EXPORT ViewConfig : public osg::Object
{
public:
ViewConfig() {}
ViewConfig(const ViewConfig& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY) : osg::Object(rhs,copyop) {}
META_Object(osgViewer,ViewConfig);
/** configure method that is overridden by Config subclasses.*/
virtual void configure(osgViewer::View& /*view*/) const {}
/** convenience method for getting the relevant display settings to use.*/
virtual osg::DisplaySettings* getActiveDisplaySetting(osgViewer::View& view) const;
};
//osgViewer/config/SingleWindow.cpp
class OSGVIEWER_EXPORT SingleWindow : public ViewConfig
{
public:
SingleWindow():_x(0),_y(0),_width(-1),_height(-1),_screenNum(0),_windowDecoration(true),_overrideRedirect(false) {}
SingleWindow(int x, int y, int width, int height, unsigned int screenNum=0):_x(x),_y(y),_width(width),_height(height),_screenNum(screenNum),_windowDecoration(true),_overrideRedirect(false) {}
SingleWindow(const SingleWindow& rhs, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY):ViewConfig(rhs,copyop), _x(rhs._x),_y(rhs._y),_width(rhs._width),_height(rhs._height),_screenNum(rhs._screenNum),_windowDecoration(rhs._windowDecoration), _overrideRedirect(rhs._overrideRedirect) {}
META_Object(osgViewer,SingleWindow);
virtual void configure(osgViewer::View& view) const;
void setX(int x) { _x = x; }
int getX() const { return _x; }
void setY(int y) { _y = y; }
int getY() const { return _y; }
void setWidth(int w) { _width = w; }
int getWidth() const { return _width; }
void setHeight(int h) { _height = h; }
int getHeight() const { return _height; }
void setScreenNum(unsigned int sn) { _screenNum = sn; }
unsigned int getScreenNum() const { return _screenNum; }
void setWindowDecoration(bool wd) { _windowDecoration = wd; }
bool getWindowDecoration() const { return _windowDecoration; }
void setOverrideRedirect(bool override) { _overrideRedirect = override; }
bool getOverrideRedirect() const { return _overrideRedirect; }
protected:
int _x, _y, _width, _height;
unsigned int _screenNum;
bool _windowDecoration;
bool _overrideRedirect;
};
void SingleWindow::configure(osgViewer::View& view) const
{
// 获得窗口系统API接口
osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
if (!wsi)
{
OSG_NOTICE<<"SingleWindow::configure() : Error, no WindowSystemInterface available, cannot create windows."<<std::endl;
return;
}
//获取osg:: DisplaySettings的指针,单例实例,在程序中唯一,用于设置
osg::DisplaySettings* ds = getActiveDisplaySetting(view);
//新建一个显示设备特性实例
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits(ds);
//尝试检查系统环境变量DISPLAY,并调用ScreenIdentifier::setScreenIdentifier函数,
//将其中的内容按照“hostName:0.0”的格式解析为系统的主机名称(hostName),
//显示数(在Win32下必须为0)和屏幕数(0或者其它数字)
traits->readDISPLAY();
if (traits->displayNum<0) traits->displayNum = 0;
//根据立体显示模式的不同,窗口特性中的模板位数等参量也会有所区分。
traits->screenNum = _screenNum;
traits->x = _x;
traits->y = _y;
traits->width = _width;
traits->height = _height;
traits->windowDecoration = _windowDecoration;
traits->overrideRedirect = _overrideRedirect;
traits->doubleBuffer = true;
traits->sharedContext = 0;
if (traits->width<=0 || traits->height<=0 )
{
osg::GraphicsContext::ScreenIdentifier si;
si.readDISPLAY();
// displayNum has not been set so reset it to 0.
if (si.displayNum<0) si.displayNum = 0;
si.screenNum = _screenNum;
unsigned int width, height;
wsi->getScreenResolution(si, width, height);
if (traits->width<=0) traits->width = width;
if (traits->height<=0) traits->height = height;
}
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
// 默认给主相机设置有个gc
view.getCamera()->setGraphicsContext(gc.get());
//一切有关视窗API接口的工作都是由GraphicsWindowWin32,GraphicsWindowX11和GraphicsWindowCarbon
//这三个类及其协作类来完成
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(gc.get());
if (gw)
{
//调用osgGA::GUIEventAdapter::setWindowRectangle记录新建立的窗口设备的大小,
//因而这个设备上产生的键盘和鼠标事件可以以此为依据。
OSG_INFO<<"SingleWindow::configure - GraphicsWindow has been created successfully."<<std::endl;
gw->getEventQueue()->getCurrentEventState()->setWindowRectangle(traits->x, traits->y, traits->width, traits->height );
}
else
{
OSG_NOTICE<<"SingleWindow::configure - GraphicsWindow has not been created successfully."<<std::endl;
return;
}
double fovy, aspectRatio, zNear, zFar;
view.getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
//设置主摄像机_camera的透视投影参数,并设置新的Viewport视口
double newAspectRatio = double(traits->width) / double(traits->height);
double aspectRatioChange = newAspectRatio / aspectRatio;
if (aspectRatioChange != 1.0)
{
view.getCamera()->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
}
view.getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
//这实质上相当于在渲染的过程中执行glDrawBuffer和glReadBuffer,从而自动设置此摄像机想要绘制和读取的缓存
view.getCamera()->setDrawBuffer(buffer);
view.getCamera()->setReadBuffer(buffer);
if (ds->getKeystoneHint())
{
if (ds->getKeystoneHint() && !ds->getKeystoneFileNames().empty())
{
osgViewer::Keystone::loadKeystoneFiles(ds);
}
if (ds->getKeystones().empty()) ds->getKeystones().push_back(new Keystone);
view.assignStereoOrKeystoneToCamera(view.getCamera(), ds);
}
else if (ds->getStereo() && ds->getUseSceneViewForStereoHint())
{
view.assignStereoOrKeystoneToCamera(view.getCamera(), ds);
}
}
千万不要简单地使用new来创建新的GraphicsContext指针,因为相比起来,createGraphicsContext还完成了这样一些工作:
1、获取窗口系统API接口,即GraphicsContext::WindowingSystemInterface的实例;
2、执行setUndefinedScreenDetailsToDefaultScreen函数,如果用户没有设置屏幕数,则自动设置为缺省值0;
3、返回WindowingSystemInterface::createGraphicsContext的值。