查看: 2047|回复: 11

如何用drawcallback提取场景到图片文件

[复制链接]

该用户从未签到

发表于 2014-6-24 23:08:11 | 显示全部楼层 |阅读模式
之前看了很多说法,也到国外osg论坛看过了,还是不太能理解怎么用osg::camera的drawcallback进行场景图像的提取。请大哥们帮帮忙。小弟感激不尽啊!

该用户从未签到

 楼主| 发表于 2014-6-24 23:14:42 | 显示全部楼层
附上我的查阅资料写的程序,但是总是提取额到全黑的图片.

   

该用户从未签到

 楼主| 发表于 2014-6-24 23:26:25 | 显示全部楼层
struct MyCameraFinalDrawCallback : public osg::Camera:rawCallback
{
    MyCameraFinalDrawCallback(osg::Image* image):
        _image(image)
    {
    }

    virtual void operator () (const osg::Camera& /*camera*/) const
    {
        if (_image && _image->getPixelFormat()==GL_RGBA && _image->getDataType()==GL_UNSIGNED_BYTE)
        {
            // we'll pick out the center 1/2 of the whole image,
            int column_start = _image->s()/4;
            int column_end = 3*column_start;

            int row_start = _image->t()/4;
            int row_end = 3*row_start;


            // and then invert these pixels
            for(int r=row_start; r<row_end; ++r)
            {
                unsigned char* data = _image->data(column_start, r);
                for(int c=column_start; c<column_end; ++c)
                {
                    (*data) = 255-(*data); ++data;
                    (*data) = 255-(*data); ++data;
                    (*data) = 255-(*data); ++data;
                    (*data) = 255; ++data;
                }
            }


            // dirty the image (increments the modified count) so that any textures
            // using the image can be informed that they need to update.
            _image->dirty();
        }
        else if (_image && _image->getPixelFormat()==GL_RGBA && _image->getDataType()==GL_FLOAT)
        {
            // we'll pick out the center 1/2 of the whole image,
            int column_start = _image->s()/4;
            int column_end = 3*column_start;

            int row_start = _image->t()/4;
            int row_end = 3*row_start;

            // and then invert these pixels
            for(int r=row_start; r<row_end; ++r)
            {
                float* data = (float*)_image->data(column_start, r);
                for(int c=column_start; c<column_end; ++c)
                {
                    (*data) = 1.0f-(*data); ++data;
                    (*data) = 1.0f-(*data); ++data;
                    (*data) = 1.0f-(*data); ++data;
                    (*data) = 1.0f; ++data;
                }
            }

            // dirty the image (increments the modified count) so that any textures
            // using the image can be informed that they need to update.
           // _image->dirty();
        }

    }

    osg::Image* _image;
};


int main()
{   
        osg::ref_ptr<osg::Group> root = new osg::Group;
    osg::ref_ptr<osg::Node> model=new osg::Node;       
    model=osgDB::readNodeFile("glider.osg");
               
        osg::ref_ptr<osg::Camera> camera=new osg::Camera;
        osg::ref_ptr<osg::Image> image= new osg::Image;            

        camera->setViewport(0,0,800,600);

    camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f));
       
        camera->attach(osg::Camera::COLOR_BUFFER,image.get());

        camera->addChild(model);

        image->allocateImage(800,600,1,GL_RGB,GL_UNSIGNED_BYTE);

        camera->setFinalDrawCallback(new MyCameraFinalDrawCallback(image));
       
        root->addChild(camera.get());
       
        osg::ref_ptr<osgViewer::Viewer> viewer =new osgViewer::Viewer;

        viewer->setSceneData(root.get());
       
        viewer->frame();

        osgDB::writeImageFile(*image,"first.bmp");

        viewer->run();

该用户从未签到

发表于 2014-6-25 18:25:28 | 显示全部楼层
您可以参考osgprerender或者osgposter例子

该用户从未签到

 楼主| 发表于 2014-6-25 22:36:24 | 显示全部楼层
array 发表于 2014-6-25 18:25
您可以参考osgprerender或者osgposter例子

王锐哥,您好。我提取出一帧图像了,之前的错误是将 osgDB::writeImageFile(*image,"x.bmp")放到viewer.run之前了。应该是还没执行frame loop就输出是不可行的。我刚开始学osg,对这些语句还没有很深的概念。然后,有什么方法能输出连续的图像吗?我想把这些图像连成视频给simulink做输入。另外,锐哥还知道osg与simulink有什么办法做数据交换么?给小弟指个方向。谢谢您!

该用户从未签到

发表于 2014-6-26 08:25:03 | 显示全部楼层
while(!viewer->done)
{
        viewer->frame();

        osgDB::writeImageFile(*image,"first.bmp");
}

该用户从未签到

 楼主| 发表于 2014-6-26 22:33:16 | 显示全部楼层
wwwanghao 发表于 2014-6-26 08:25
while(!viewer->done)
{
        viewer->frame();

我试过这样的方法。不行。还是要viewer.run才可以生成图片。您知道怎么连续生成图片么?谢谢!

该用户从未签到

发表于 2014-6-26 22:52:11 | 显示全部楼层
为什么不行啊?是Image数据没读进来,还是怎么的,也不说清楚,我这样做就能保存

该用户从未签到

 楼主| 发表于 2014-6-27 16:18:13 | 显示全部楼层
wwwanghao 发表于 2014-6-26 22:52
为什么不行啊?是Image数据没读进来,还是怎么的,也不说清楚,我这样做就能保存

嗯 应该是数据没读进来。其他代码都一样,如果把
      viewer->run();
     osgDB::writeImageFile(*image,"first.bmp");

换成
while(!viewer->done)
{
        viewer->frame();

        osgDB::writeImageFile(*image,"first.bmp");
}
后,就又是黑屏了。奇了怪了。

   

该用户从未签到

发表于 2014-6-27 19:28:51 | 显示全部楼层
这才是正常的,渲染到纹理,屏幕就不显示了,看看你的图片是否保存成功

该用户从未签到

 楼主| 发表于 2014-6-27 20:30:30 | 显示全部楼层
wwwanghao 发表于 2014-6-27 19:28
这才是正常的,渲染到纹理,屏幕就不显示了,看看你的图片是否保存成功

图片也是全黑的。

该用户从未签到

 楼主| 发表于 2014-7-1 17:33:07 | 显示全部楼层
clallan 发表于 2014-6-27 20:30
图片也是全黑的。

更新一下进展。现已能成功提取图像流,并作成了视频。使用的是screencapturehandler.
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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