OSG嵌入到Qt5

该博客介绍了如何在Qt5环境下使用OpenSceneGraph(OSG)库创建一个3D图形窗口,并展示了一个3D圆柱体。通过Qt的QOpenGLWidget子类化,结合OSG的GraphicsWindowEmbedded和Viewer类,实现了OSG场景与Qt窗口的集成。同时,代码中处理了鼠标事件和视口调整,以及设置了TrackballManipulator用于交互式视角控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OSG版本:3.6.5    32位

Qt版本:5.12.4      32位

VS版本:VS2017

找了一天,发现了这样一段代码,实现了OSG嵌入到Qt5中。

代码如下:

#include <QApplication>
#include <QMainWindow>
#include <QOpenGLWidget>
#include <QMouseEvent>
#include <QWheelEvent>
#include <QDesktopWidget>
#include <QScreen>
#include <QtGlobal>
#include <QWindow>

#include <osg/ref_ptr>
#include <osgViewer/GraphicsWindow>
#include <osgViewer/Viewer>
#include <osg/Camera>
#include <osg/ShapeDrawable>
#include <osg/StateSet>
#include <osg/Material>
#include <osgGA/EventQueue>
#include <osgGA/TrackballManipulator>

#include <iostream>
#include <stdio.h>

class QtOSGWidget : public QOpenGLWidget
{
public:
	QtOSGWidget(qreal scaleX, qreal scaleY, QWidget* parent = 0)
		: QOpenGLWidget(parent)
		, _mGraphicsWindow(new osgViewer::GraphicsWindowEmbedded(this->x(), this->y(),
			this->width(), this->height()))
		, _mViewer(new osgViewer::Viewer)
		, m_scaleX(scaleX)
		, m_scaleY(scaleY)
	{
		osg::Cylinder* cylinder = new osg::Cylinder(osg::Vec3(0.f, 0.f, 0.f), 0.25f, 0.5f);
		osg::ShapeDrawable* sd = new osg::ShapeDrawable(cylinder);
		sd->setColor(osg::Vec4(0.8f, 0.5f, 0.2f, 1.f));
		osg::Geode* geode = new osg::Geode;
		geode->addDrawable(sd);

		osg::Camera* camera = new osg::Camera;
		camera->setViewport(0, 0, this->width(), this->height());
		camera->setClearColor(osg::Vec4(0.9f, 0.9f, 1.f, 1.f));
		float aspectRatio = static_cast<float>(this->width()) / static_cast<float>(this->height());
		camera->setProjectionMatrixAsPerspective(30.f, aspectRatio, 1.f, 1000.f);
		camera->setGraphicsContext(_mGraphicsWindow);

		_mViewer->setCamera(camera);
		_mViewer->setSceneData(geode);
		osgGA::TrackballManipulator* manipulator = new osgGA::TrackballManipulator;
		manipulator->setAllowThrow(false);
		this->setMouseTracking(true);
		_mViewer->setCameraManipulator(manipulator);
		_mViewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
		_mViewer->realize();
	}


	virtual ~QtOSGWidget() {}

	void setScale(qreal X, qreal Y)
	{
		m_scaleX = X;
		m_scaleY = Y;
		this->resizeGL(this->width(), this->height());
	}

protected:

	virtual void paintGL() {
		_mViewer->frame();
	}

	virtual void resizeGL(int width, int height)
	{
		this->getEventQueue()->windowResize(this->x()*m_scaleX, this->y() * m_scaleY, width*m_scaleX, height*m_scaleY);
		_mGraphicsWindow->resized(this->x()*m_scaleX, this->y() * m_scaleY, width*m_scaleX, height*m_scaleY);
		osg::Camera* camera = _mViewer->getCamera();
		camera->setViewport(0, 0, this->width()*m_scaleX, this->height()* m_scaleY);
	}

	virtual void initializeGL() {
		osg::Geode* geode = dynamic_cast<osg::Geode*>(_mViewer->getSceneData());
		osg::StateSet* stateSet = geode->getOrCreateStateSet();
		osg::Material* material = new osg::Material;
		material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
		stateSet->setAttributeAndModes(material, osg::StateAttribute::ON);
		stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
	}

	virtual void mouseMoveEvent(QMouseEvent* event)
	{
		this->getEventQueue()->mouseMotion(event->x()*m_scaleX, event->y()*m_scaleY);
	}

	virtual void mousePressEvent(QMouseEvent* event)
	{
		unsigned int button = 0;
		switch (event->button()) {
		case Qt::LeftButton:
			button = 1;
			break;
		case Qt::MiddleButton:
			button = 2;
			break;
		case Qt::RightButton:
			button = 3;
			break;
		default:
			break;
		}
		this->getEventQueue()->mouseButtonPress(event->x()*m_scaleX, event->y()*m_scaleY, button);
	}

	virtual void mouseReleaseEvent(QMouseEvent* event)
	{
		unsigned int button = 0;
		switch (event->button()) {
		case Qt::LeftButton:
			button = 1;
			break;
		case Qt::MiddleButton:
			button = 2;
			break;
		case Qt::RightButton:
			button = 3;
			break;
		default:
			break;
		}
		this->getEventQueue()->mouseButtonRelease(event->x()*m_scaleX, event->y()*m_scaleY, button);
	}

	virtual void wheelEvent(QWheelEvent* event)
	{
		int delta = event->delta();
		osgGA::GUIEventAdapter::ScrollingMotion motion = delta > 0 ?
			osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN;
		this->getEventQueue()->mouseScroll(motion);
	}

	virtual bool event(QEvent* event)
	{
		bool handled = QOpenGLWidget::event(event);
		this->update();
		return handled;
	}

private:

	osgGA::EventQueue* getEventQueue() const {
		osgGA::EventQueue* eventQueue = _mGraphicsWindow->getEventQueue();
		return eventQueue;
	}

	osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> _mGraphicsWindow;
	osg::ref_ptr<osgViewer::Viewer> _mViewer;
	qreal m_scaleX, m_scaleY;
};

int main(int argc, char** argv)
{
	QApplication qapp(argc, argv);

	QMainWindow window;
	QtOSGWidget* widget = new QtOSGWidget(1, 1, &window);
	window.setCentralWidget(widget);
	window.show();

	return qapp.exec();
}

原文地址:https://gist.github.com/vicrucann/874ec3c0a7ba4a814bd84756447bc798

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值