• OSG嵌入QT的简明总结2


    正文

    我之前在这篇博文《OSG嵌入QT的简明总结》中论述了OSG在QT中显示的可视化问题。其中提到官方提供的osgQt项目(地址:https://github.com/openscenegraph/osgQt )很久前已经更新了。但是我一直没有时间同步更新,最近重新尝试了一下,还是有一些问题。

    原先的osgQt版本是兼容Qt4的QGLWidget,这个类Qt官方准备废弃了,现在使用的OpenGL支持组件是QOpenGLWidget,新的osgQt项目就是基于这个类来进行扩展的。在项目中提供了一个例子osgviewerQt,我稍微试用了一下,将其修改成自己的代码时发现了问题,就是渲染的场景宽高比不正确,尤其是将窗体设置成很长或者很窄的时候。我还特意在这个项目中提交了issue:I tried the demo in the project, and the correct aspect ratio cannot be displayed

    后续也有人回答了这个问题,一个解决方案就是需要在初始化响应函数中设置相机投影矩阵的宽高比。我改写的例子如下:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    int main(int argc, char* argv[]) {
      QSurfaceFormat format = QSurfaceFormat::defaultFormat();
    
    #ifdef OSG_GL3_AVAILABLE
      format.setVersion(3, 2);
      format.setProfile(QSurfaceFormat::CoreProfile);
      format.setRenderableType(QSurfaceFormat::OpenGL);
      format.setOption(QSurfaceFormat::DebugContext);
    #else
      format.setVersion(2, 0);
      format.setProfile(QSurfaceFormat::CompatibilityProfile);
      format.setRenderableType(QSurfaceFormat::OpenGL);
      format.setOption(QSurfaceFormat::DebugContext);
    #endif
      format.setDepthBufferSize(24);
      // format.setAlphaBufferSize(8);
      format.setSamples(8);
      format.setStencilBufferSize(8);
      format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
      QSurfaceFormat::setDefaultFormat(format);
    
      QApplication app(argc, argv);
    
      osgQOpenGLWidget widget;
    
      QObject::connect(&widget, &osgQOpenGLWidget::initialized, [&widget] {
        // set up the camera manipulators.
        widget.getOsgViewer()->setCameraManipulator(
            new osgGA::TrackballManipulator());
    
        // add the state manipulator
        widget.getOsgViewer()->addEventHandler(new osgGA::StateSetManipulator(
            widget.getOsgViewer()->getCamera()->getOrCreateStateSet()));
    
        // add the thread model handler
        widget.getOsgViewer()->addEventHandler(new osgViewer::ThreadingHandler);
    
        // add the window size toggle handler
        widget.getOsgViewer()->addEventHandler(new osgViewer::WindowSizeHandler);
    
        // add the stats handler
        widget.getOsgViewer()->addEventHandler(new osgViewer::StatsHandler);
    
        // add the record camera path handler
        widget.getOsgViewer()->addEventHandler(
            new osgViewer::RecordCameraPathHandler);
    
        // add the LOD Scale handler
        widget.getOsgViewer()->addEventHandler(new osgViewer::LODScaleHandler);
    
        // add the screen capture handler
        widget.getOsgViewer()->addEventHandler(new osgViewer::ScreenCaptureHandler);
    
        // load the data
        std::string filename = "C:/Data/001/010137001.obj";
        osg::ref_ptr<osg::Node> loadedModel = osgDB::readRefNodeFile(filename);
    
        // optimize the scene graph, remove redundant nodes and state etc.
        osgUtil::Optimizer optimizer;
        optimizer.optimize(loadedModel);
    
        widget.getOsgViewer()->setSceneData(loadedModel);
    
        //增加宽高比设置
        QSize size = widget.size();    
        float aspectRatio =
            static_cast<float>(size.width()) / static_cast<float>(size.height());
        widget.getOsgViewer()->getCamera()->setProjectionMatrixAsPerspective(
            60.f, aspectRatio, 1.f, 1000.f);
    
        return 0;
      });
    
      widget.resize(200, 600);
      widget.show();
    
      return app.exec();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90

    上述例子确实可以让场景显示正常,即使窗体宽设置为200,高设置为600。不过我发现了另外一个问题,按S显示帧数的时候帧数比之前的解决方案低很多。之前的解决方案帧数可以达到200帧,但是这个解决方案帧数大概在90帧左右。

    具体看了一下其封装的osgQOpenGLWidget的实现,我觉得可能有两个原因,第一个是渲染的帧函数中有同步锁,不知道会不会有所影响。第二个是这个解决方案获取的帧数好像是自己计算的,与OSG内部计算的帧数不同似乎也正常。不过我这里是不太敢用这个解决方案了,目前还是使用之前的解决方案,以后有机会还是自己研究一下其中的实现。

    参考

    1. OpenSceneGraph + QOpenGLWidget - minimal example
    2. OSG 使用Qt的QOpenGLWidget
  • 相关阅读:
    基于 Vite + Vue3 的组件库打包并发布到npm
    Web服务(02)——Web服务器中间件
    基于变化点 copula 优化算法中的贝叶斯研究(Matlab代码实现)
    8/21 牛客补题+cf思维+tarjan
    sass的常用语法总结
    Spring-@Component和@Configuration的区别
    字体反爬积累知识
    [题]宝物筛选 #单调队列优化
    18.10 组复制常见问题
    Linux C基础(5)
  • 原文地址:https://blog.csdn.net/charlee44/article/details/133894624