我正在使用OpenSceneGraph和Qt开发一个仿真软件。模拟可以在同一个虚拟世界中包含多个机器人。我对视图的要求如下:
- 显示静态世界摄像机的能力
- 显示机器人摄像机的能力
- 能够移动这些视图和/或堆叠它们
为了完成这些任务,我制作了一个"OSGWidget",它使用Osg Viewer在QGLWidget中渲染场景。这个OSGWidget又被放入一个QDockWidget中,QDockWidget可以移动和/或堆叠,以满足该需求。
问题是,当使用多个单一的查看器在不同的小部件中渲染相同的场景时,我得到奇怪的渲染行为。也就是说,纹理不能正确显示,有时甚至根本不能显示。
我已经环顾了SO和OSG论坛,虽然人们有类似的问题,但我所看到的唯一回应是建议切换到OSG CompositeViewer。出于我的目的,我想避免使用它,因为它打破了我对渲染相同场景的可移动和可堆叠小部件的期望要求。
这是Osg难以处理的棘手情况吗?我看到一些帖子说这不是OSG"应该工作"的方式,但他们并没有真正提供事实来支持这种说法。有人做过类似的事情或有任何想法/见解吗?如果需要的话,我可以提供代码片段,但由于这可能与Osg的思想相矛盾,我将等待得到一些回应。
感谢来自评论和其他几个站点的一些帮助,我能够成功地从CompositeViewer获得我想要的行为。
基本上,所有OSG视图都通过我的"WidgetDriver",其中包含一个CompositeViewer。
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选项,将线程模型设置为singlethread,将releaseContextAtEndOfFrame设置为false,如果你想让一个线程作用于多个视图,这是必要的。如果你像我一样使用小部件驱动程序,你会想这样做。