查看: 2203|回复: 15

关于setviewport问题

[复制链接]

该用户从未签到

发表于 2011-5-23 20:28:20 | 显示全部楼层 |阅读模式
请问:
     setviewport这个函数的宽和高,直接用确定的数去设置,例如:令width=256,height=256。之后再用readpixel函数读取等大小的图像,为什么获得的图片和视口大小不一致?
     是由于这两个函数参数的单位不一致吗?而且在固定视口宽高和横纵比后,为什么窗口最大化后,相机视口大小也会随着变?
     不知道说明白没有,望见谅!

该用户从未签到

发表于 2011-5-24 09:16:12 | 显示全部楼层
能否用简单但是能说明问题的代码来表述您的问题?

该用户从未签到

 楼主| 发表于 2011-5-24 09:57:51 | 显示全部楼层
回复 2# array


    恩,麻烦你了!
#define width  256
#define height  256

viewer[2]->getcamera()->setviewport(new osg::Viewport(0,0,width,height));


... ...
osg::GraphicsContext *rgc = renderInfo.getState()->getGraphicsContext();
if(rgc->getTraits())
{
   Glenum pixelformat;
    if(rgc->getTraits()->alpha)
    pixelformat = GL_RGBA;
   else
    pixelformat = GL_RGB;
readpixel(0,0,width,height,pixelformat,GL_UNSIGNED_BYTE);
}


之后检查捕获的图片大小是256*256的,可是图片捕获的范围大于视口设置的大小。不应该是一样大的吗?
还有为什么程序窗口变大,视口也会随着变大呢,不应该是不变的吗?

该用户从未签到

 楼主| 发表于 2011-5-24 13:40:10 | 显示全部楼层
没有人遇到类似的问题吗?

该用户从未签到

发表于 2011-5-24 13:42:44 | 显示全部楼层
求解.......

该用户从未签到

发表于 2011-5-24 17:59:22 | 显示全部楼层
请您先弄明白视口的概念

该用户从未签到

 楼主| 发表于 2011-5-25 08:50:47 | 显示全部楼层
回复 6# liuzhiyu123


    恩,在我理解是屏幕像素单位。对吧?屏幕像素和在内存中读取的像素单位是一回事吗?
我再去好好看看,也希望您能教授点知识。

该用户从未签到

发表于 2011-5-25 08:58:59 | 显示全部楼层
我无法把您的代码和您的问题对应起来,您遇到了什么问题,您的截图结果是怎样的?

该用户从未签到

 楼主| 发表于 2011-5-26 08:36:17 | 显示全部楼层
回复 8# array


    我再去好好找找原因吧!
    之后在来请教,谢谢了!

该用户从未签到

 楼主| 发表于 2011-5-31 16:53:25 | 显示全部楼层
回复 9# robinhit

打扰了,帮忙看下,写的不清楚的地方请告诉我!
    #define IMAGE_WIDTH 256
#define IMAGE_HEIGHT 256

//左相机抓图类的成员函数定义
LeftCameraCallBack:eftCameraCallBack(osg::ref_ptr<osg::Image>image)
    {
                _image = image;
                /*counter = 0;*/
    }

void LeftCameraCallBack:perator()( osg::RenderInfo &renderInfo)const
        {
                osg::GraphicsContext* gc = renderInfo.getState()->getGraphicsContext();
                if (gc->getTraits())
                {
                        GLenum pixelFormat;

                        // 计算图象数据格式GL_RGB或GL_RGBA,即是否带alpha通道
                        // 也可以理解成像素是24bits或32bits
                        if (gc->getTraits()->alpha)
                                pixelFormat = GL_RGBA;
                        else
                                pixelFormat = GL_RGB;

                        // 获得图象的大小,即为当前窗口的大小
                        int width = IMAGE_WIDTH;
                        int height = IMAGE_HEIGHT;

                        // 使用osg::Image类提供的函数来读取像素数据并保存到osg::Image中
                        _image->allocateImage(width,height,1,pixelFormat,GL_UNSIGNED_BYTE);
                        _image->readPixels(0,0,width,height,pixelFormat,GL_UNSIGNED_BYTE);
                       

                }
        }


void CCoreOSG::InitCameraConfig(void)
{
        // 局部变量存放窗口矩形
        RECT rect;

        // 创建一个复合viewer
        mViewer = new osgViewer::CompositeViewer();


        // 得到当前窗口矩形
        ::GetWindowRect(m_hWnd, &rect);

        osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;

        // 初始化窗口变量,为OSG所用
        osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);

        // 设置一些个参数
        traits->screenNum = 3;
        traits->x = 0;
        traits->y = 0;
        traits->width = GetSystemMetrics (SM_CXSCREEN);
        traits->height =GetSystemMetrics (SM_CYSCREEN);
        traits->windowDecoration = false;
        traits->doubleBuffer = true;
        traits->sharedContext = 0;
        traits->setInheritedWindowPixelFormat = true;
        traits->inheritedWindowData = windata;

        // 创建图形上下文
        osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits.get());
   
        /* debug */
        gc->setClearColor(osg::Vec4f(0.0f, 0.0f, 0.0f, 1.0f));
        gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


        //全局图像View
        viewers[1] = new osgViewer::View;
        viewers[1]->setName("View two");
        mViewer->addView(viewers[1]);
        viewers[1]->setUpViewOnSingleScreen(1);
        leftCamera = viewers[1]->getCamera();

        viewers[1]->setSceneData(mRoot.get());
        viewers[1]->getCamera()->setViewport(new osg::Viewport(0,0, traits->width, traits->height));
        viewers[1]->getCamera()->setGraphicsContext(gc);
        viewers[1]->getCamera()->setProjectionMatrixAsPerspective(60.0, double(traits->width) / double(traits->height), 0.001, 1000.0);
       
        viewers[1]->setCameraManipulator(trackball);
        viewers[1]->addEventHandler( new osgViewer::WindowSizeHandler );
       
        //左眼相机View
        viewers[2] = new osgViewer::View;
        viewers[2]->setName("View two");
        mViewer->addView(viewers[2]);
        //viewers[2]->setUpViewOnSingleScreen(2);
        leftCamera = viewers[2]->getCamera();


        viewers[2]->setSceneData(mRoot.get());
        viewers[2]->getCamera()->setViewport(new osg::Viewport(0,0, IMAGE_WIDTH,IMAGE_HEIGHT));
        viewers[2]->getCamera()->setGraphicsContext(gc);
        viewers[2]->getCamera()->setProjectionMatrixAsPerspective(60.0,1.0, 0.001, 1000.0);
        viewers[2]->setCameraManipulator(new osgGA::TrackballManipulator);

        limage_c = new osg::Image();
        viewers[2]->getCamera()->setPostDrawCallback(new LeftCameraCallBack(limage_c.get()));

}

osg::ref_ptr<osg::Image> CCoreOSG::getLeftImage()
{
        return limage_c;
}

void CRobotSimView::OnTestSaveleft()
{
        // TODO: 在此添加命令处理程序代码
        osg::ref_ptr<osg::Image>leftImage = mOSG->getLeftImage();
        std::string leftC;
        CString str = "LeftCamera";
        CString strCounter;
        strCounter.Format("%d", leftcounter);
        str =  str + strCounter+".bmp";
        leftC = (LPCTSTR)str;
        osgDB::writeImageFile(*(leftImage.get()),leftC);
}


程序就是调用CRobotSimView::OnTestSaveleft函数,来保存图像的。

视口.jpg

截图的效果就是这样的,readpixels函数截的图片正好是我想要的大小,可是为什么大于视口的范围啊?而且当整个窗口大小变化时,为什么这个视口的大小也随着变啊?

该用户从未签到

发表于 2011-6-1 08:29:12 | 显示全部楼层
如果视口的大小不跟随窗口变化的话,我想更多的人会大叫起来——因为这样会导致更不合理的结果~~我想您需要考虑一下自己的策略问题,为什么您一定要限制视口不变?您有没有别的替代方法?

该用户从未签到

 楼主| 发表于 2011-6-1 09:11:06 | 显示全部楼层
回复 11# array


    早上好,array!
    所截取的图片要传给别的程序用,那边只接收大小为256*256的图片,进行相关计算。所以要限制视口的大小。

    要是利用下边的width与height去设置视口setViewport(new osg::Viewport(0,0,traits->width/4,traits->height/4));
    同样的用readPixels(0,0,width/4,height/4,pixelformat,GL_UNSIGNED_BYTE);这样所截的图片与视口的大小一样。
    表面上看都是利用相同的值,为什么会有这种差别呢?是不是直接利用确定的数设置视口的值与从osg::GraphicsContext::Traits 得到的值所附带的属性不一样呢。



    osg::ref_ptr<osg::GraphicsContext::Traits>traits = new osg::GraphicsContext::Traits;

     traits->width = GetSystemMetrics(SM_CXSCREEN);
     traits->height= GetSystemMetrics(SM_CYSCREEN);

该用户从未签到

发表于 2011-6-1 16:40:22 | 显示全部楼层
你渲染到一个固定大小的纹理不就好了

该用户从未签到

发表于 2011-6-2 09:31:43 | 显示全部楼层
tianxiao的方法是更好的,即使用RTT的方式

该用户从未签到

 楼主| 发表于 2011-6-3 09:23:52 | 显示全部楼层
回复 13# tianxiao888


    恩,这我不是很明白,采用别的办法了,在一个确定大小的对话框中渲染了。谢谢你的建议!
   有时间我会好好研究下你的方法。

该用户从未签到

 楼主| 发表于 2011-6-3 09:25:11 | 显示全部楼层
回复 14# array


    谢谢了!这个方法不是很懂,有时间我好好研究下!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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