4

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

  • 能够显示静态世界相机
  • 能够显示机器人摄像头
  • 能够移动这些视图和/或堆叠它们

为了完成这些任务,我制作了一个“OSGWidget”,它使用一个 Osg Viewer 在 QGLWidget 中渲染场景。这个 OSGWidget 又被放置在一个 QDockWidget 中,该 QDockWidget 可以四处移动和/或堆叠,以满足该要求。

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

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

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

4

1 回答 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)是必要的。如果你像我一样使用小部件驱动程序,你会想要这样做。
于 2013-04-12T15:21:03.227 回答