通过阅读osgViewer::View::setUpViewInWindow()了解osg最基础的操作

根据给定的窗口参数来创建一个图形设备

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的值
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值