上一篇处理了QGraphicsView的鼠标、按键事件,本篇接着嵌入OSGEarth。
新建一继承自EventAdapter(一)的类GraphicsView,完成OSGEarth的嵌入工作。实现思路是QGraphicsView的Viewport用OpenGL来绘制,这样才可以完全OSG的update。而要完成每帧的更新,则需要一个定时器,每隔10ms更新一次,即每10ms调用一次OSG的frame操作。
实现代码:graphicsview.h
class GraphicsView : public EventAdapter
{
Q_OBJECT
public:
GraphicsView(QWidget* parent = 0);
~GraphicsView();
osgViewer::Viewer* getOSGViewer(){ return m_pViewer; }
osg::Group* getRoot(){ return m_pSceneData; }
osgEarth::MapNode* getMapNode(){ return m_pMapNode; }
const osgEarth::SpatialReference* getSRS(){ return m_pMapSRS; }
osgEarth::Util::EarthManipulator* getManipulator(){ return m_pEarthManipulator; }
protected:
// 完成OSG每一帧的update操作
virtual void drawBackground(QPainter *painter, const QRectF& rect);
virtual void timerEvent(QTimerEvent *event);
private:
void init();
private:
osgEarth::Map* m_pMap;
osg::Group* m_pSceneData;
osg::StateSet* m_pStateSet;
osgViewer::Viewer* m_pViewer;
osgEarth::MapNode* m_pMapNode;
osgEarth::Util::SkyNode* m_pSkyNode;
const osgEarth::SpatialReference* m_pMapSRS;
osgEarth::Util::EarthManipulator* m_pEarthManipulator;
};
几个get方法,获取OSGEarth相关的Viewer、Group、MapNode、SpatialReference、EarthManipulator等给外部使用。
实现代码:graphicsview.cpp
GraphicsView::GraphicsView(QWidget *parent)
{
this->setScene(new QGraphicsScene);
init();
}
GraphicsView::~GraphicsView()
{
}
void GraphicsView::init()
{
// QGraphicsView的Viewport一定要设置为QGLWidget,因为只有这样才能用OpenGL来对OSG进行更新
QGLWidget* glViewPort = new QGLWidget;
glViewPort->setMouseTracking(true);
glViewPort->setMaximumSize(2000, 2000);
this->setViewport(glViewPort);
this->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
startTimer(10);
osg::Group* pRoot = new osg::Group;
pRoot->setName("root");
m_pSceneData = new osg::Group;
m_pSceneData->setName("SceneData");
m_pStateSet = new osg::StateSet;
m_pStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
pRoot->setStateSet(m_pStateSet);
pRoot->addChild(m_pSceneData);
// 使用earth文件的方式进行数据加载,驱动为TMS
osg::Node* node = osgDB::readNodeFile("../LiuPanShui.earth");
if (node)
{
m_pMapNode = osgEarth::MapNode::findMapNode(node);
m_pMapNode->setName("MapNode");
m_pMap = m_pMapNode->getMap();
m_pMapSRS = m_pMapNode->getMapSRS();
}
m_pViewer = new osgViewer::Viewer;
m_pEarthManipulator = new osgEarth::Util::EarthManipulator;
m_pEarthManipulator->getSettings()->setMinMaxPitch(-90.0, -7.0);
m_pViewer->setCameraManipulator(m_pEarthManipulator);
m_pViewer->addEventHandler(new osgViewer::StatsHandler);
m_pViewer->addEventHandler(new osgGA::StateSetManipulator(m_pViewer->getCamera()->getOrCreateStateSet()));
m_pViewer->getCamera()->addCullCallback(new osgEarth::Util::AutoClipPlaneCullCallback(m_pMapNode));
m_pViewer->getCamera()->setNearFarRatio(0.0000002);
m_pViewer->getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
m_pViewer->setUpViewerAsEmbeddedInWindow(0, 0, width(), height());
m_pViewer->setSceneData(pRoot);
m_pGraphicsWindow = dynamic_castGraphicsWindow*>(
m_pViewer->getCamera()->getGraphicsContext());
m_pEarthManipulator->setViewpoint(osgEarth::Util::Viewpoint(
104.81443, 26.60379, 1811.2336, 0.0, -90.0, 5000));
m_pSkyNode = osgEarth::Util::SkyNode::create(m_pMapNode);
m_pSkyNode->setName("SkyNode");
// 设置时间;
osgEarth::DateTime dateTime(2015, 8, 15, 6);
osgEarth::Util::Ephemeris* ephemeris = new osgEarth::Util::Ephemeris;
m_pSkyNode->setEphemeris(ephemeris);
m_pSkyNode->setDateTime(dateTime);
m_pSkyNode->attach(m_pViewer, 0);
m_pSkyNode->setLighting(true);
m_pSkyNode->addChild(m_pMapNode);
pRoot->addChild(m_pSkyNode);
}
void GraphicsView::timerEvent(QTimerEvent *event)
{
this->scene()->update();
}
void GraphicsView::drawBackground(QPainter *painter, const QRectF& rect)
{
if (painter->paintEngine()->type() != QPaintEngine::OpenGL2)
{
return;
}
// Save the painter state
painter->save();
painter->beginNativePainting();
// OSG帧更新
m_pViewer->frame();
painter->endNativePainting();
painter->restore();
}