В настоящее время мы сталкиваемся со следующей проблемой: у нас есть приложение, которое должно отображать множество отдельных сцен OpenSceneGraph в разных виджетах Qt. Например, у нас может быть один виджет Qt, изображающий сферу, а другой виджет изображает икосаэдр. Поскольку мы используем OpenSceneGraph 3.0.1, мы следовали за osgViewerQt example from the official documentation для реализации этого.Несколько виджетов Qt, отображающих разные узлы OpenSceneGraph без потери производительности
Пример кода использует QTimer
для того, чтобы заставить обновления для просмотра виджета:
connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
_timer.start(10);
Проблемы начинаются, когда в настоящее время мы хотим создать и показать несколько виджетов. Поскольку каждый виджет имеет свой собственный таймер, производительность быстро уменьшает с количеством открытых виджетов. Мало того, что взаимодействие с виджетами OSG очень медленное, также взаимодействие с другое Qt-виджеты заметно отстают. Даже половина недавней четырехъядерной системы почти перегружена, когда открыто около 5 окон. Эта проблема определенно не относится к нашему графическому оборудованию. Другие приложения могут отображать гораздо большие сцены (Blender, Meshlab и т. Д.) без любое отрицательное воздействие на производительность.
Итак, подведем итог: что было бы лучшим способом создания нескольких виджетов Qt, показывающих разные сцены OpenSceneGraph без влияние производительности?
То, что мы уже пробовали:
- Мы уже рассматривали с помощью одного
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;
};
Однако это также привело к заметному снижению производительности. Каждый поток по-прежнему требует большого времени процессора (что неудивительно, так как основное взаимодействие все еще обрабатывается таймером). Единственным преимуществом этого подхода является то, что по крайней мере взаимодействие с другими Qt виджетов остается возможным.
Идеальное решение для нас было бы виджет, который срабатывает только перерисовывать запросы всякий раз, когда пользователь взаимодействует с ним, например, нажав, дважды щелкнув, прокрутки и т.д. Более точно, этот виджет должен оставаться idle, пока не потребуется обновление. Что-то похожее на это возможно на всех? Мы будем приветствовать любые предложения.