查看: 1994|回复: 2

根据Qt的widget生成动态纹理的问题

[复制链接]

该用户从未签到

发表于 2009-7-27 21:06:40 | 显示全部楼层 |阅读模式
因为项目需要,我现在要实时将qwidget的界面动态显示在osg场景中,根据osgtexture2d的例子我做了一个测试程序,实现了动态更换纹理的功能,但刷新速度却非常的慢,不足以实际应用,希望有经验的老师,同学能指点以下。主要代码如下:
class JaTextureUpdateCallback : public osg::NodeCallback
{
private:
        typedef void(*JaGetDisplayDataFunc)(int *w, int *h, unsigned char *data);

        osg::Texture2D* myTexture;       
        JaGetDisplayDataFunc getDisplayData;       
        osg::Image * myImage;
        tttttt t;
public:       
        JaTextureUpdateCallback(const char *libName, osg::Texture2D*image): myTexture(image)
        {
                //getDisplayData = (JaGetDisplayDataFunc)QLibrary::resolve(libName, "getDisplayData");               
                myImage = new osg::Image;
                myImage->allocateImage(t.width(), t.height(), 1, GL_RGBA, GL_UNSIGNED_BYTE);

                //myImage->setDataVariance(osg::Object:YNAMIC);
                myTexture->setImage(0,myImage);
                t.show();
        }

        void __getDisplayDataFunc(int *w, int *h, unsigned char **data)
        {       
               

                QPixmap pixmap(t.size());
                t.render(&pixmap);
                QImage image = QGLWidget::convertToGLFormat(pixmap.toImage());
                *w = image.width();
                *h = image.height();
                int __size = image.numBytes() * sizeof(unsigned char);
                unsigned char *__data = image.bits();
                free(*data);
                *data = (unsigned char *)malloc(__size);
                memcpy(*data, __data, __size);
               
        }

        virtual void operator ()(osg::Node* node, osg::NodeVisitor* nv)
        {
                /*if(!getDisplayData)
                        return;*/

                unsigned char *data = myImage->data();
                int w, h;
                __getDisplayDataFunc(&w, &h, &data);
                myImage->dirty();
        //        getDisplayData(&w, &h, data);
                //osg::ref_ptr<osg::Image > __image = new osg::Image;
               
               
                /*myImage->setImage(w, h, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, data,
                        osg::Image::AllocationMode::USE_MALLOC_FREE);*/
                //myTexture->setImage(0,0);

                //myTexture->setImage(0,myImage);
                traverse(node, nv);
        }

       
};

/***********************************************************************************************/

JaDynamicTextureNode::JaDynamicTextureNode(double width, double height,
                                                                                   const char *libName)
{
        addChild(createDisplayGraph(width, height, libName));
}

JaDynamicTextureNode::~JaDynamicTextureNode(void)
{
}

//创建预渲染场景
osg::Node* JaDynamicTextureNode::createDisplayGraph(double width, double height,
                                                                                                        const char *libName)
{
        osg::Group* group = new osg::Group;

        //创建定点数组
        osg::Vec3 top_left(0,-width / 2.0f, height / 2.0f);
        osg::Vec3 bottom_left(0,-width / 2.0f, -height / 2.0f);
        osg::Vec3 bottom_right(0,width / 2.0f, -height / 2.0f);
        osg::Vec3 top_right(0,width / 2.0f, height / 2.0f);

        // create the geometry for the wall.
        osg::Geometry* geom = new osg::Geometry;

        osg::Vec3Array* vertices = new osg::Vec3Array(4);
        (*vertices)[0] = top_left;
        (*vertices)[1] = bottom_left;
        (*vertices)[2] = bottom_right;
        (*vertices)[3] = top_right;
        geom->setVertexArray(vertices);

        osg::Vec2Array* texcoords = new osg::Vec2Array(4);
        (*texcoords)[0].set(0.0f,1.0f);
        (*texcoords)[1].set(0.0f,0.0f);
        (*texcoords)[2].set(1.0f,0.0f);
        (*texcoords)[3].set(1.0f,1.0f);
        geom->setTexCoordArray(0,texcoords);

        osg::Vec3Array* normals = new osg::Vec3Array(1);
        (*normals)[0].set(0.0f,-1.0f,0.0f);
        geom->setNormalArray(normals);
        geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

        osg::Vec4Array* colors = new osg::Vec4Array(1);
        (*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
        geom->setColorArray(colors);
        geom->setColorBinding(osg::Geometry::BIND_OVERALL);

        geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS,0,4));

        osg::Geode* geom_geode = new osg::Geode;
        geom_geode->addDrawable(geom);
        group->addChild(geom_geode);


        // set up the texture state.   
        osg::Texture2D* texture = new osg::Texture2D;
        texture->setDataVariance(osg::Object::DYNAMIC); // protect from being optimized away as static state.
        texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D:INEAR);
        texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);       

        osg::StateSet* stateset = geom->getOrCreateStateSet();
        stateset->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
        /*stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
        stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);*/
        //osg::Image * __image = new osg::Image;
        //texture->setImage(0, __image);

        // set the update callback to cycle through the various min and mag filter modes.
        group->setUpdateCallback(new JaTextureUpdateCallback(libName, texture));

        return group;
}

不论是采用osg::Image::setImage()或是采用如上代码自己调整image的内存数据,都会使刷新速度下降,若将上述代码中的myImage->dirty();屏蔽掉而不强制texture重新加载image则刷新很快。
请大家给予帮助,谢谢。

该用户从未签到

发表于 2009-7-28 12:20:49 | 显示全部楼层
暂时我无法判断您的问题所在。您可以参考osgdb_gif插件中GifImageStream的做法,以及ImageSequence类的实现

该用户从未签到

 楼主| 发表于 2009-7-29 09:46:31 | 显示全部楼层
问题已解决,其实很简单,只要将窗体的尺寸规格化为2的n次方,或是使用osg::texturerectangel就可以得到非常高的帧率,不过使用osg::TextureRectangle还是比osg::Texture2D慢一些。另外采用上上述方法时,窗体最好不要在运行期改变大小,即使要改变也只能小不能大。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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