查看: 1303|回复: 5

关于窗口、视口的问题

[复制链接]

该用户从未签到

发表于 2015-7-14 15:12:28 | 显示全部楼层 |阅读模式
这几天拿来以前的一个程序不小心多想了一下,发现了一个小问题,但是让我痛苦不堪,那就是原来我做过一个多视口的程序,如下:
#include "../Common/Common.h"
#include <Windows.h>

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/stateSetManipulator>
#include <osgGA/GUIEventHandler>
#include <osg/Camera>

#ifdef _DEBUG
#pragma comment(lib,"../Debug/Common.lib")
#else
#pragma comment(lib,"../Release/Common.lib")
#endif


class ChangWinSize : public osgGA::GUIEventHandler
{
public:
        ChangWinSize(){ _first = true;}
        bool handle(const osgGA::GUIEventAdapter &ea,osgGA::GUIActionAdapter &aa)
        {
                if( _first ){
                        _first = false;

                        osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*> (&aa);
                        osgViewer::Viewer::Windows ws;

                        viewer->getWindows(ws);

                        if(!ws.empty()){
                                for(osgViewer::Viewer::Windows::iterator iter = ws.begin() ; iter<ws.end() ; ++iter){
                                        (*iter)->setWindowRectangle(50,50,600,300);
                                        //(*iter)->setWindowDecoration(false);
                                }
                        }
                       
                }

                return false;
        }

private:
        bool _first;
};

int main()
{
        osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
        osg::ref_ptr<osg::Camera> masterCamera = new osg::Camera;
        osg::ref_ptr<osg::Camera> slaveCamera = new osg::Camera;

        //
        osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
        if( !wsi ){
                std::cout<<"Get wsi null"<<std::endl;
                return NULL;
        }

        unsigned int width,height;
        wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0),width,height);

        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
        traits->x = 0;
        traits->y = 0;
        traits->width = width;
        traits->height = height;
        traits->doubleBuffer = true;
        traits->sharedContext = 0;
        traits->windowDecoration = true;

        osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits);
        if( !gc->valid() ){
                std::cout<<"gc is null"<<std::endl;
                return NULL;
        }

        //width = 600,height = 300;
        //设置相机属性
        masterCamera->setGraphicsContext(gc);
        masterCamera->setViewMatrix(osg::Matrix::identity());
        masterCamera->setProjectionMatrix(osg::Matrix::identity());
        masterCamera->setViewport(0,0,width/2,height);
        masterCamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

        slaveCamera->setGraphicsContext(gc);
        slaveCamera->setViewport(width/2,0,width/2,height);
        slaveCamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);

        //添加从相机数据
        slaveCamera->addChild(osgDB::readNodeFile("cow.osg"));


        viewer->addSlave(masterCamera);
        viewer->addSlave(slaveCamera,false);


        viewer->addEventHandler(new ChangWinSize);
        viewer->setSceneData(osgDB::readNodeFile("cow.osg"));

        viewer->run();
        return 0;
}
这样的话显示的图片1确实是两个视口,如图:


但是如果这时候我发现主相机和从相机的视口场合宽中的数据均为:
masterCamera->setViewport(0,0,width/2,height);
slaveCamera->setViewport(width/2,0,width/2,height);
width = 1920
height = 1080
这个是我的显示器的分辨率,不过这时候窗口不是利用回调改成了如下:
(*iter)->setWindowRectangle(50,50,600,300);
600*300了吗?
这是怎么回事?
我做了如下改动,把设置相机的代码如下改一下,其他的均不改变:
masterCamera->setViewport(0,0,600/2,300);
slaveCamera->setViewport(600/2,0,600/2,300);
得到的图像如下:

图2

图2


不应该视口是以像素为单位的话,这样才应该是正常均分这个窗口吗?
哎,查了好些个窗口、视口、以及设备坐标的东西,讲的都乱糟糟的,现在把以前的理解全部推翻了,这个越想越不正确,该怎么解释,请各位大神指点指点。

该用户从未签到

 楼主| 发表于 2015-7-14 15:15:45 | 显示全部楼层
不好意思,第一张图片没有上传,现在补上:

图1

图1

该用户从未签到

发表于 2015-7-15 00:02:53 | 显示全部楼层
原因是你的相机窗口没有覆盖掉或者更准确的说法是使用掉整个opengl窗口,
因为masterCamera->setViewport(0,0,600/2,300);
slaveCamera->setViewport(600/2,0,600/2,300);,而opengl窗口的长宽是traits->width,traits->height;

setWindowRectangle(50,50,600,300);是对opengl窗口进行变换到(x,y,width,height),当然相机视口也等比例缩放,自然会出现你那种情况

该用户从未签到

 楼主| 发表于 2015-7-15 21:42:30 | 显示全部楼层
buaahc 发表于 2015-7-15 00:02
原因是你的相机窗口没有覆盖掉或者更准确的说法是使用掉整个opengl窗口,
因为masterCamera->setViewport( ...

我做了一下实验,它应该按初始化的比例进行记录视口和窗口的大小关系,但是就是不知道在那里将这种关系进行了记录。查了好几遍源码,也没有发现这个记录和每次绘制前更改视口和窗口大小的东西,不晓得你知不知到。OpenGL这部分是自己做的,也就是我们不在代码中自己记录这个比例的话,它原来是多少就是多少,但是明显通过实验得知OSG是可以记录这个比例关系并且每次都可以更新回调从新设置视口和窗口的实际大小,所以我想找到究竟在那里设置的。

该用户从未签到

发表于 2015-7-15 22:11:37 | 显示全部楼层
本帖最后由 buaahc 于 2015-7-15 22:16 编辑

setWindowRectangle()把这个函数的源代码看明白,看明白里面的resize()

该用户从未签到

 楼主| 发表于 2015-7-16 18:58:19 | 显示全部楼层
buaahc 发表于 2015-7-15 22:11
setWindowRectangle()把这个函数的源代码看明白,看明白里面的resize()

谢了,看了好久,终于明白了一点。摸清了一点GraphicsContext、GraphicsWindow、GraphicsWindonWin32以及WindowingSystemInterface之间的关系。虽然现在看的有点晕晕乎乎,每个类之间的关系有点复杂,但是至少找到了其中视口、窗口、以及投影矩阵之前的关系。谢谢。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表