首页 文章

OpenSceneGraph和多个查看器

提问于
浏览
3

我正在使用OpenSceneGraph和Qt开发模拟软件 . 模拟可以涉及同一虚拟世界中的多个机器人 . 我对观点的要求如下:

  • 能够显示静态世界相机

  • 能够显示机器人相机

  • 能够移动这些视图和/或堆叠它们

为了完成这些任务,我制作了一个'OSGWidget',它使用Osg Viewer在QGLWidget中渲染场景 . 这个OSGWidget又放在一个可以移动和/或堆叠的QDockWidget中,满足了这个要求 .

问题是当使用多个奇异的查看器在不同的小部件中渲染相同的场景时,我会得到奇怪的渲染行为 . 即,纹理不能正确显示或有时甚至根本不显示 .

我已经浏览了SO和OSG论坛,虽然人们遇到了类似的问题,但我看到的唯一回应是建议切换到Osg CompositeViewer . 出于我的目的,我想避免使用它,因为它打破了我对移动和可堆叠小部件呈现相同场景的期望要求 .

这是一个棘手的情况,奥斯格不容易处理吗?我看过几篇帖子说这不是OSG应该如何“工作”,但他们并没有真正提供支持这种说法的事实 . 有没有人做过类似的事情或有任何想法/见解?如果需要,我可以提供代码片段,但由于这可能与Osg的意识形态相矛盾,我将等待得到一些回应 .

1 回答

  • 3

    感谢评论和其他几个网站的帮助,我能够成功地从CompositeViewer获得我想要的行为 .

    基本上,所有OSG视图都通过包含CompositeViewer的“WidgetDriver” .

    class OsgWidgetDriver {
    public:
        void init() {
            compositeViewer = new osgViewer::CompositeViewer;
            compositeViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
            compositeViewer->setReleaseContextAtEndOfFrameHint(false);
        }
    
        void start() {
            initialized = true;
        }
    
        void stop() {
            compositeViewer->stopThreading();
            compositeViewer->setDone(true);
        }
    
        void updateFrame() {
            if (initialized)
                compositeViewer->frame();
        }
    
        void addView(osgViewer::View *view) { compositeViewer->addView(view); }
        bool isInitialized() { return initialized; }
    protected:
        bool initialized;
        osgViewer::CompositeViewer *compositeViewer;
    };
    

    然后,每当我创建一个新的Qt OSG Widget时,我都将osg :: View移交给驱动程序 . 我让驱动程序更新渲染窗口,而Qt仍然可以相应地更新QWidget . 它甚至允许我将小部件放在QDockWidget中,这样我就可以移动它们并根据需要堆叠它们 .

    关于该过程的一些最终说明,如果其他人想要这样做:

    • 当多个OSG查看器正在查看一个场景时,您很可能会遇到奇怪的纹理显示问题 . 如果发生这种情况,请使用osgUtil :: Optimizer :: TextureVisitor将所有纹理设置为"UnrefImageAfterApply = false" . 这将允许跨多个osg :: View实例显示正确的纹理 .

    • 如果您希望单个线程作用于多个视图,我需要在上面设置的CompositeViewer选项,将模型线程化为SingleThreaded,将releaseContextAtEndOfFrame线程化为false . 如果你像我一样使用小部件驱动程序,你会想要这样做 .

相关问题