OSG 内嵌 QT,包括osgQT.lib库编译到渲染出窗口和事件机制实现

      转转请注明出处 By Villean http://write.blog.csdn.net/postedit/18266991

      在使用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等才能起作用,但是你编译的话会出现错误

原因是qt框架实现信号草,需要通过moc.exe对qobject项目处理生成Moc_xxx.cpp从而将信号草关联实现。我们需要自己实现moc 文件的生成,方法是在vs工程右键属性找到

添加,其他类似的也如此。然后编译一次会报错,但是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();
	}
}





  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值