gpt4 book ai didi

c++ - 多个 Qt 小部件描绘不同的 OpenSceneGraph 节点而没有性能损失

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:32:05 25 4
gpt4 key购买 nike

我们目前面临以下问题:我们有一个应用程序需要在不同的 Qt 小部件中显示大量单独的 OpenSceneGraph 场景。例如,我们可能有一个描绘球体的 Qt 小部件,而另一个描绘二十面体的小部件。由于我们使用的是 OpenSceneGraph 3.0.1,因此我们遵循了 osgViewerQt example from the official documentation为了实现这一点。

示例代码使用 QTimer 来强制更新查看器小部件:

    connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );
_timer.start( 10 );

当我们想要创建和显示多个 小部件时,问题就开始了。由于每个小部件都有自己的计时器,因此性能会随着打开小部件的数量迅速下降。不仅与 OSG 小部件的交互非常缓慢,与其他 Qt 小部件的交互也明显滞后。当打开大约 5 个窗口时,即使是半新的四核系统也几乎不堪重负。此问题绝对与我们的图形硬件无关。其他应用程序可能会渲染更大的场景(Blender、Meshlab 等), 不会对性能产生任何负面影响。

因此,总结一下:创建多个显示不同 OpenSceneGraph 场景的 Qt 小部件的最佳方法是什么? 不会影响性能?

我们已经尝试过的:

  • 我们已经考虑过使用单个 osgViewer::CompositeViewer渲染所有场景对象。但是,我们放弃了这个想法现在因为它可能会与单个小部件进行交互非常复杂。
  • 我们尝试将每个 osgViewer::CompositeViewer 的渲染部分放在一个单独的线程中,详见 osgQtWidgets example .

我们的第二次尝试(使用线程)大致如下所示:

   class ViewerFrameThread : public OpenThreads::Thread
{
public:
ViewerFrameThread(osgViewer::ViewerBase* viewerBase):
_viewerBase(viewerBase) {}

~ViewerFrameThread()
{
cancel();
while(isRunning())
{
OpenThreads::Thread::YieldCurrentThread();
}
}

int cancel()
{
_viewerBase->setDone(true);
return 0;
}

void run()
{
int result = _viewerBase->run();
}

osg::ref_ptr<osgViewer::ViewerBase> _viewerBase;
};

但是,这导致性能显着下降。每个线程仍然需要大量 CPU 时间(这并不奇怪,因为基本交互仍然由计时器处理)。这种方法的唯一优点是至少可以与其他 Qt 小部件进行交互。

对我们来说,理想的解决方案是一个只在用户与其交互时触发重绘请求的小部件,例如通过单击双击滚动等。更准确地说,这个小部件应该保持空闲直到需要更新。有没有可能类似的东西?我们欢迎任何建议。

最佳答案

针对此问题尝试了多种模型后,我很高兴地报告说我找到了一个运行完美的模型。我正在使用一个 QThread(类似于上面描述的线程),它基本上包装了一个 osgViewer::ViewerBase 对象并简单地调用 viewer->run().

保持低 CPU 使用率的技巧是强制 OpenSceneGraph 仅按需渲染。尝试了各种选项后,我发现以下两个设置效果最好:

viewer->setRunFrameScheme( osgViewer::ViewerBase::ON_DEMAND );
viewer->setThreadingModel( osgViewer::ViewerBase::CullDrawThreadPerContext );

像这样修改的查看器将不会使用虚假的 CPU 周期进行连续更新,同时仍然使用多个线程进行剔除和绘制。其他线程模型在某些情况下当然可能表现更好,但对我来说,这就足够了。

如果有人尝试类似的解决方案,请注意某些操作现在需要明确的重绘请求。例如,当处理与 OSG 对象的交互 或当您编写自己的CameraManipulator 类时,调用viewer->requestRedraw()< 不会有什么坏处 更改查看器设置后。否则,查看器只会在小部件需要重绘时刷新。

简而言之,这是我学到的:

  • 不要使用计时器进行渲染
  • 暂时不要放弃多线程
  • 没有什么比阅读源代码更好的了(官方 OSG 示例有时缺乏细节,但源代码从不说谎......)

关于c++ - 多个 Qt 小部件描绘不同的 OpenSceneGraph 节点而没有性能损失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10893930/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com