osg 观察窗口加载无响应的解决方法

场景为加载窗口,经常在->block()缓解无响应,推测是路径问题或CPU占用过大。

1 LoadScene();->

2   {
3      osg::ref_ptr<UserOperation> pUserOperation = 
4           new UserOperation(UserOperation::Operation_AddView, m_pView);
5       m_pParent->GetSimCompositeViewer()->addUpdateOperation(pUserOperation);
6        pUserOperation->block();//经常无响应
7    }

由于该步骤并没有任何路径调用,因此应该为CPU占用过高导致的问题。

解决方法:在5-6行之间添加如下代码。其中ViewerFrameThread是用于打开多个qt窗口的类。貌似可以节省CPU占用。

m_pParent->GetViewerFrameThread()->SetRun(true); 

具体用法参考两个资料:

c++ - Multiple Qt widgets depicting different OpenSceneGraph nodes without performance loss - Stack Overflow

防丢copy:

The problems now begin when we want to create and show multiple widgets. Since each widget comes with its own timer, performance rapidly decreases with the number of open widgets. Not only is the interaction with the OSG widgets very slow, also the interaction with other Qt widgets noticeably lags. Even a halfway recent quad-core system is almost overwhelmed when approximately 5 windows are open. This issue is definitely not related to our graphics hardware. Other applications may render much larger scenes (Blender, Meshlab etc.) without any negative performance impact.

So, to summarize: What would be the best way of creating multiple Qt widgets showing different OpenSceneGraph scenes without a performance impact?

What we already tried:

  • We already considered using a single osgViewer::CompositeViewer for rendering all scene objects. However, we discarded this idea for now because it will probably make interactions with a single widget very complicated.
  • We tried putting the rendering portion of each osgViewer::CompositeViewer in a separate thread as detailed by the osgQtWidgets example.

Our second try (using threads) looked roughly like this:

   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;
    };

However, this also resulted in a remarkable performance decrease. Each thread still requires much CPU time (which is not surprising as the basic interaction is still handled with a timer). The only advantage of this approach is that at least interaction with other Qt widgets remain possible.

The ideal solution for us would be a widget that only fires redraw requests whenever the user interacts with it, for example by clickingdouble-clickingscrolling etc. More precisely, this widget should remain idle until there is a need for an update. Is something akin to this possible at all? We would welcome any suggestions.

Having tried out several models for this problem, I am happy to report that I found one that is working perfectly. I am using a QThread (similar to the thread described above) that essentially wraps an osgViewer::ViewerBase object and simply calls viewer->run().

The trick to keep CPU usage low is to force OpenSceneGraph to render on demand only. Having tried out the various options, I found the following two settings to work best:

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

A viewer that is modified like this will not use spurious CPU cycles for continuous updates while still using multiple threads for culling and drawing. Other threading models might of course perform better in some cases, but for me, this was sufficient.

If any one else attempts a similar solution, be warned that some operations now require explicit redraw requests. For example, when handling interactions with OSG objects or when you are writing your own CameraManipulator class, it doesn't hurt to call viewer->requestRedraw() after changing viewer settings. Else, the viewer will only refresh when the widget requires a repaint.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值