天天看點

OSG 内嵌 QT,包括osgQT.lib庫編譯到渲染出視窗和事件機制實作

OSG 内嵌 QT,包括osgQT.lib庫編譯到渲染出視窗和事件機制實作

      在使用OSG内嵌QT的做UI的時候 遇到不少障礙,而關于此類的文章網上很少,于是有了這篇文章,寫的比較籠統,對于寫的不清楚的地方,希望大家留言探讨。

      另外,代碼因為是邊研究邊寫,一些代碼備援不規範,如果這篇文章大家很有幫助,我會整理後再次釋出。

     本文一共解決如下幾個問題:

                                                     1.osgQt所需庫的編譯

      2.osg簡單渲染例子的顯示

                                                      3.基本事件的響應(也就是osg自帶例子的實作方式,太局限,不能再項目中使用)

  4.OSG qt中信号槽的實作(重要)。

     一、OSGQt.lib

             這個庫檔案一開始編譯 廢了一番周折,要注意這麼幾點。首先你别使用qt5.1.1,使用qt4.6版本,5.1.1沒有通過qmake配置成功,應該是版本不支援的原因,而且qt5.1.1的庫在osg中必須設定為單線程,這個跟osgCegui相同,這是qt個很傻×的一個做法。然後你應該做的是:到qt管網下載下傳qt4.6---安裝--配置環境變量(很重要,怎麼配置網上很多)---安裝配置osg環境等就不用說了----然後在編譯osg庫的時候重點來了,在cmake中找到qmake目錄指定這一項,讓路徑指向qt目錄bin 下的qmake檔案,在再cmake中找到with_QT的字樣 選中,config,general,打開指定osg生成目錄下的sln工程,會出現osgQT這一個項目,右鍵編譯即可。

             完事後,在生成目錄找到OSGQt.lib和相關的dll檔案拷貝到你的osg相應目錄即可大功告成。

    二、簡單例子

        這個比較簡單,基本有了庫檔案後這個很容易了解,文字最後 會貼出項目的示例代碼。

   三、osg自帶的例子,中有一個事件相應方式

class MyPushButton :public QPushButton
{
public:
	MyPushButton(const QString &text) : QPushButton(text)
	{
	}
protected:
	virtual void mousePressEvent(QMouseEvent *event)
	{
		std::cout << " push " << std::endl;
	}
};
           

這個相應方式是重寫按鈕,然後重寫其方法嗎,這個顯然不能滿足我們的要求,以後多個控件豈不糾結。 四、信号槽的實作 這個如果你是通過cmkae配置出來的項目,相應的一些可以配置好,但是通過win32 控制台做的項目,很多需要自己配置。 首先在你繼承qwidget的項目要加上Q_OBJECT宏,這樣你的 slots和connect等才能起作用,但是你編譯的話會出現錯誤

OSG 内嵌 QT,包括osgQT.lib庫編譯到渲染出視窗和事件機制實作

原因是qt架構實作信号草,需要通過moc.exe對qobject項目處理生成Moc_xxx.cpp進而将信号草關聯實作。我們需要自己實作moc 檔案的生成,方法是在vs工程右鍵屬性找到

OSG 内嵌 QT,包括osgQT.lib庫編譯到渲染出視窗和事件機制實作

添加,其他類似的也如此。然後編譯一次會報錯,但是debug目錄會生成相應的Moc檔案,将他拖入工程目錄,然後編譯運作即可通過。測試源代碼如下:

#include <QWidget>
 
#include <QPushButton>
class QtDemo : public QWidget
{
	Q_OBJECT

public:
	QtDemo(QWidget *parent = 0);
	//~QtDemo();
public slots:
	void mClick();

private:
	
};
           
#include "a.h"
#include "QtDemo.h"
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/TrackballManipulator>

#include <osgWidget/Browser>
#include <osgWidget/Box>
#include <osg/Notify>
#include <osgQt/QGraphicsViewAdapter>
#include <osgQt/QWidgetImage>
#include <osgQt/QWebViewImage>
#include <osgQt/GraphicsWindowQt>

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QVBoxLayout>
#include <QMainWindow>
#include <QtEvents>
#include <QLabel>

QPushButton *button;
//
QtDemo::QtDemo(QWidget *parent)
	:   QWidget(parent)
{
	
	connect(button,SIGNAL(clicked()),this,SLOT(mClick()));
}

void QtDemo::mClick()
{
	std::cout<<"clicked"<<std::endl;
}

class ViewFrameThread :public OpenThreads::Thread
{
public:
	ViewFrameThread(osgViewer::ViewerBase *viewBase,bool doQApplicationExit):m_viewerBase(viewBase),m_doQApplicationExit(doQApplicationExit)
	{
	}
	~ViewFrameThread()
	{
		cancel();
		while(isRunning())
		{
			OpenThreads::Thread::YieldCurrentThread();
		}
	}
	int cancel()
	{
		m_viewerBase->setDone(true);
		return 0;
	}

	void run()
	{
		int result=m_viewerBase->run();
		if(m_doQApplicationExit) QApplication::exit(result);
	}
private:
	osg::ref_ptr<osgViewer::ViewerBase> m_viewerBase;
	bool m_doQApplicationExit;
};

//設計一個button
class MyPushButton :public QPushButton
{
public:
	MyPushButton(const QString &text) : QPushButton(text)
	{
	}
protected:
	virtual void mousePressEvent(QMouseEvent *event)
	{
		std::cout << " push " << std::endl;
	}
};

osg::Camera *createCameraWithQwidget(int x,int y,int w,int h)
{
	osg::DisplaySettings *ds=osg::DisplaySettings::instance().get();
	osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits(ds);
	traits->windowDecoration = true;
	traits->x = x;
	traits->y = y;
	traits->width = w;
	traits->height = h;
	traits->doubleBuffer = true;

	osg::ref_ptr<osg::Camera> camera = new osg::Camera;
	osg::ref_ptr<osgQt::GraphicsWindowQt> graphic = new osgQt::GraphicsWindowQt(traits.get());
	graphic->getGraphWidget()->setAcceptDrops(false);
	graphic->getGraphWidget()->setMinimumSize(10, 10);
	camera->setGraphicsContext(graphic.get());
	camera->setClearColor( osg::Vec4(0.39, 0.39, 0.39, 1.0) );
	GLenum buffer = traits->doubleBuffer ? GL_BACK : GL_FRONT;
	camera->setDrawBuffer(buffer);
	camera->setReadBuffer(buffer);
	camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
	camera->setProjectionMatrixAsPerspective(
		30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 1000.0f );

	return camera.release();
}

int main(int argc,char **argv)
{

	QApplication app(argc, argv);
	
	//聲明節點
	osg::ref_ptr<osg::Group> root  =new osg::Group;
	osg::ref_ptr<osg::Node> node2=osgDB::readNodeFile("glider.osg");
	osg::ref_ptr<osg::Node> nodeButton=new osg::Node;
	QGraphicsScene *scene;
	QGraphicsView view;
	osg::Camera *camera=new osg::Camera;
	osg::ref_ptr<osgViewer::Viewer> viewer=new osgViewer::Viewer;
	//viewer->setCamera(camera);
	viewer->setCameraManipulator(new osgGA::TrackballManipulator);
	//osgQt::GraphicsWindowQt *gw=dynamic_cast<osgQt::GraphicsWindowQt*>(camera->getGraphicsContext());
	//osgQt::GLWidget *glWidget=gw->getGLWidget();
	QWidget *widget=new QWidget;
	//開始設計
	{
		widget->setWindowTitle("Title");
		widget->setLayout(new QVBoxLayout);

		QString text("中文顯示 測試。");
		QLabel *label=new QLabel(text);
		label->setWordWrap(true);
		label->setTextInteractionFlags(Qt::TextEditorInteraction);

		QPalette palette = label->palette();
		palette.setColor(QPalette::Highlight, Qt::darkBlue);
		palette.setColor(QPalette::HighlightedText, Qt::white);
		label->setPalette(palette);

		QScrollArea* scrollArea = new QScrollArea;
		scrollArea->setWidget(label);

		widget->layout()->addWidget(scrollArea);
		button=new QPushButton("zheshi  an niu");
		MyPushButton *slotButton=new MyPushButton("這是 信号草按鈕");
		widget->layout()->addWidget(button);
		widget->layout()->addWidget(slotButton);
		widget->setGeometry(0, 0, 800, 600);
		//app.connect(slotButton,SIGNAL(clicked()),this,SLOT(mClick()));
		// 加入一個按鈕
	}
	QtDemo qtdemo;
	//開始加入osg視窗渲染
	osg::ref_ptr<osgQt::QWidgetImage> widgetImage=new osgQt::QWidgetImage(widget);
	widgetImage->getQWidget()->setAttribute(Qt::WA_TranslucentBackground);
	widgetImage->getQGraphicsViewAdapter()->setBackgroundColor(QColor(0,0,0,0));
	scene=widgetImage->getQGraphicsViewAdapter()->getQGraphicsScene();
	osg::Geometry *quad=osg::createTexturedQuadGeometry(osg::Vec3(0,0,0),osg::Vec3(1,0,0),osg::Vec3(0,1,0), 1, 1);
	osg::Geode *geode=new osg::Geode;
	geode->addDrawable(quad);
	osg::MatrixTransform *mt=new osg::MatrixTransform;
	osg::Texture2D *texture=new osg::Texture2D(widgetImage);
	texture->setResizeNonPowerOfTwoHint(false);
	texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
	texture->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE);
	texture->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE);
	mt->getOrCreateStateSet()->setTextureAttributeAndModes(0,texture,osg::StateAttribute::ON);
	osgViewer::InteractiveImageHandler *handler;
	if (true)
	{
		mt->setMatrix(osg::Matrix::rotate(osg::Vec3(0,1,0),osg::Vec3(0,0,1)));
		mt->addChild(geode);
		handler=new osgViewer::InteractiveImageHandler(widgetImage);
	}
	else
	{
		camera->setProjectionResizePolicy(osg::Camera::FIXED);
		camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
		camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
		camera->setViewMatrix(osg::Matrix::identity());
		camera->setClearMask(GL_DEPTH_BUFFER_BIT);
		camera->setRenderOrder(osg::Camera::POST_RENDER);
		camera->addChild(geode);
		camera->setViewport(0,0,1024,768);
		mt->addChild(camera);
		handler=new osgViewer::InteractiveImageHandler(widgetImage,texture,camera);
		mt->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
		mt->getOrCreateStateSet()->setMode(GL_BLEND,osg::StateAttribute::ON);
		mt->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
		mt->getOrCreateStateSet()->setAttribute(new osg::Program);
	}

	osg::Group *overlay=new osg::Group;
	overlay->addChild(mt);
	root->addChild(overlay);
	quad->setEventCallback(handler);
	quad->setCullCallback(handler);

	//加入牛和浏覽器視窗
	root->addChild(node2);
	osg::ArgumentParser arguments(&argc,argv);
	osg::ref_ptr<osgQt::QWebViewImage> image=new osgQt::QWebViewImage;
	image->navigateTo("http://www.baidu.com");
	osgWidget::GeometryHints hints(osg::Vec3(0.0f,0.0f,0.0f),
		                                   osg::Vec3(1.0f,0.0f,0.0f),
		                                   osg::Vec3(0.0f,0.0f,1.0f),
		                                   osg::Vec4(1.0f,1.0f,1.0f,1.0f),
		                                   osgWidget::GeometryHints::RESIZE_HEIGHT_TO_MAINTAINCE_ASPECT_RATIO);
	osg::ref_ptr<osgWidget::Browser> browser=new osgWidget::Browser;
	//root->addChild(browser);
	browser->assign(image.get(),hints);
	
	//節點加入viewer中 運作
	viewer->setSceneData(root.get());
	//app.connect(button,SIGNAL(clicked()),button,SLOT(quit()));
	if (true)
	{
		ViewFrameThread viewThread(viewer.get(),true);
		viewThread.startThread();
		return QApplication::exec();
	}
}
           

繼續閱讀