osg完美嵌入到Qt(实现各种事件响应)

最近做东西需要osg三维渲染与Qt界面结合,网上查了不少都是不完整的。自己写不出来就想到了一个比较无耻的办法,把osgQt中的GraphicsWindowQt文件下的内容粘贴出来,将class  GLWidget : public QGLWidget 改为自己的类 class  QWidgetViewer : public QGLWidget;

这样就能完全重写QGLwidget的各种虚函数,自己的各种事件响应都解决!!

平时都做寄生虫,今天也分享点东西给大家。

目录

 QWidgetViewer.h

 QWidgetViewer.cpp

这里是怎么调用:


 QWidgetViewer.h


/*********************************************
* Author:zmh
* Email :[email protected]
* DATE  :2018/8/24
* File:QWidgetViewer.h
*   osg嵌入到Qt 干货  改写的osgQt::GraphicsWindowQt
*    直接事件响应函数重写就可以
***********************************************/


#pragma once
#include <QGLWidget>
#include <osg/Referenced>
#include <osgQt/GraphicsWindowQt>

#ifndef _DEBUG
#pragma comment(lib,"osgQt.lib")
#else
#pragma comment(lib,"osgQtd.lib")
#pragma comment(lib,"osgd.lib")
#endif

class GraphicsWindowQt1;


class  QWidgetViewer : public QGLWidget
{
	typedef QGLWidget inherited;

public:

	QWidgetViewer(QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false);
	QWidgetViewer(QGLContext* context, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false);
	QWidgetViewer(const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false);
	virtual ~QWidgetViewer();

	inline void setGraphicsWindow(GraphicsWindowQt1* gw) { _gw = gw; }
	inline GraphicsWindowQt1* getGraphicsWindow() { return _gw; }
	inline const GraphicsWindowQt1* getGraphicsWindow() const { return _gw; }

	inline bool getForwardKeyEvents() const { return _forwardKeyEvents; }
	virtual void setForwardKeyEvents(bool f) { _forwardKeyEvents = f; }

	inline bool getTouchEventsEnabled() const { return _touchEventsEnabled; }
	void setTouchEventsEnabled(bool e);

	void setKeyboardModifiers(QInputEvent* event);

	virtual void keyPressEvent(QKeyEvent* event);
	virtual void keyReleaseEvent(QKeyEvent* event);
	virtual void mousePressEvent(QMouseEvent* event);
	virtual void mouseReleaseEvent(QMouseEvent* event);
	virtual void mouseDoubleClickEvent(QMouseEvent* event);
	virtual void mouseMoveEvent(QMouseEvent* event);
	virtual void wheelEvent(QWheelEvent* event);
	virtual bool gestureEvent(QGestureEvent* event);

protected:

	int getNumDeferredEvents()
	{
		QMutexLocker lock(&_deferredEventQueueMutex);
		return _deferredEventQueue.count();
	}
	void enqueueDeferredEvent(QEvent::Type eventType, QEvent::Type removeEventType = QEvent::None)
	{
		QMutexLocker lock(&_deferredEventQueueMutex);

		if (removeEventType != QEvent::None)
		{
			if (_deferredEventQueue.removeOne(removeEventType))
				_eventCompressor.remove(eventType);
		}

		if (_eventCompressor.find(eventType) == _eventCompressor.end())
		{
			_deferredEventQueue.enqueue(eventType);
			_eventCompressor.insert(eventType);
		}
	}
	void processDeferredEvents();

	friend class GraphicsWindowQt1;
	GraphicsWindowQt1* _gw;

	QMutex _deferredEventQueueMutex;
	QQueue<QEvent::Type> _deferredEventQueue;
	QSet<QEvent::Type> _eventCompressor;

	bool _touchEventsEnabled;

	bool _forwardKeyEvents;
	qreal _devicePixelRatio;

	virtual void resizeEvent(QResizeEvent* event);
	virtual void moveEvent(QMoveEvent* event);
	virtual void glDraw();
	virtual bool event(QEvent* event);

};




class  GraphicsWindowQt1 : public osgViewer::GraphicsWindow
{
public:
	GraphicsWindowQt1(osg::GraphicsContext::Traits* traits, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0);
	GraphicsWindowQt1(QWidgetViewer* widget);
	virtual ~GraphicsWindowQt1();

	inline QWidgetViewer* getGLWidget() { return _widget; }
	inline const QWidgetViewer* getGLWidget() const { return _widget; }

	/// deprecated
	inline QWidgetViewer* getGraphWidget() { return _widget; }
	/// deprecated
	inline const QWidgetViewer* getGraphWidget() const { return _widget; }

	struct WindowData : public osg::Referenced
	{
		WindowData(QWidgetViewer* widget = NULL, QWidget* parent = NULL) : _widget(widget), _parent(parent) {}
		QWidgetViewer* _widget;
		QWidget* _parent;
	};

	bool init(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f);

	static QGLFormat traits2qglFormat(const osg::GraphicsContext::Traits* traits);
	static void qglFormat2traits(const QGLFormat& format, osg::GraphicsContext::Traits* traits);
	static osg::GraphicsContext::Traits* createTraits(const QGLWidget* widget);

	virtual bool setWindowRectangleImplementation(int x, int y, int width, int height);
	virtual void getWindowRectangle(int& x, int& y, int& width, int& height);
	virtual bool setWindowDecorationImplementation(bool windowDecoration);
	virtual bool getWindowDecoration() const;
	virtual void grabFocus();
	virtual void grabFocusIfPointerInWindow();
	virtual void raiseWindow();
	virtual void setWindowName(const std::string& name);
	virtual std::string getWindowName();
	virtual void useCursor(bool cursorOn);
	virtual void setCursor(MouseCursor cursor);
	inline bool getTouchEventsEnabled() const { return _widget->getTouchEventsEnabled(); }
	virtual void setTouchEventsEnabled(bool e) { _widget->setTouchEventsEnabled(e); }


	virtual bool valid() const;
	virtual bool realizeImplementation();
	virtual bool isRealizedImplementation() const;
	virtual void closeImplementation();
	virtual bool makeCurrentImplementation();
	virtual bool releaseContextImplementation();
	virtual void swapBuffersImplementation();
	virtual void runOperations();

	virtual void requestWarpPointer(float x, float y);

protected:

	friend class QWidgetViewer;
	QWidgetViewer* _widget;
	bool _ownsWidget;
	QCursor _currentCursor;
	bool _realized;
};

         QWidgetViewer.cpp

#include "QWidgetViewer.h"
#include <osg/DeleteHandler>
#include <osgQt/GraphicsWindowQt>
#include <osgViewer/ViewerBase>
#include <QInputEvent>
#include <QPointer>



#if (QT_VERSION>=QT_VERSION_CHECK(4, 6, 0))
# define USE_GESTURES
# include <QGestureEvent>
# include <QGesture>
#endif

using namespace osgQt;

class QtKeyboardMap
{

public:
	QtKeyboardMap()
	{
		mKeyMap[Qt::Key_Escape] = osgGA::GUIEventAdapter::KEY_Escape;
		mKeyMap[Qt::Key_Delete] = osgGA::GUIEventAdapter::KEY_Delete;
		mKeyMap[Qt::Key_Home] = osgGA::GUIEventAdapter::KEY_Home;
		mKeyMap[Qt::Key_Enter] = osgGA::GUIEventAdapter::KEY_KP_Enter;
		mKeyMap[Qt::Key_End] = osgGA::GUIEventAdapter::KEY_End;
		mKeyMap[Qt::Key_Return] = osgGA::GUIEventAdapter::KEY_Return;
		mKeyMap[Qt::Key_PageUp] = osgGA::GUIEventAdapter::KEY_Page_Up;
		mKeyMap[Qt::Key_PageDown] = osgGA::GUIEventAdapter::KEY_Page_Down;
		mKeyMap[Qt::Key_Left] = osgGA::GUIEventAdapter::KEY_Left;
		mKeyMap[Qt::Key_Right] = osgGA::GUIEventAdapter::KEY_Right;
		mKeyMap[Qt::Key_Up] = osgGA::GUIEventAdapter::KEY_Up;
		mKeyMap[Qt::Key_Down] = osgGA::GUIEventAdapter::KEY_Down;
		mKeyMap[Qt::Key_Backspace] = osgGA::GUIEventAdapter::KEY_BackSpace;
		mKeyMap[Qt::Key_Tab] = osgGA::GUIEventAdapter::KEY_Tab;
		mKeyMap[Qt::Key_Space] = osgGA::GUIEventAdapter::KEY_Space;
		mKeyMap[Qt::Key_Delete] = osgGA::GUIEventAdapter::KEY_Delete;
		mKeyMap[Qt::Key_Alt] = osgGA::GUIEventAdapter::KEY_Alt_L;
		mKeyMap[Qt::Key_Shift] = osgGA::GUIEventAdapter::KEY_Shift_L;
		mKeyMap[Qt::Key_Control] = osgGA::GUIEventAdapter::KEY_Control_L;
		mKeyMap[Qt::Key_Meta] = osgGA::GUIEventAdapter::KEY_Meta_L;

		mKeyMap[Qt::Key_F1] = osgGA::GUIEventAdapter::KEY_F1;
		mKeyMap[Qt::Key_F2] = osgGA::GUIEventAdapter::KEY_F2;
		mKeyMap[Qt::Key_F3] = osgGA::GUIEventAdapter::KEY_F3;
		mKeyMap[Qt::Key_F4] = osgGA::GUIEventAdapter::KEY_F4;
		mKeyMap[Qt::Key_F5] = osgGA::GUIEventAdapter::KEY_F5;
		mKeyMap[Qt::Key_F6] = osgGA::GUIEventAdapter::KEY_F6;
		mKeyMap[Qt::Key_F7] = osgGA::GUIEventAdapter::KEY_F7;
		mKeyMap[Qt::Key_F8] = osgGA::GUIEventAdapter::KEY_F8;
		mKeyMap[Qt::Key_F9] = osgGA::GUIEventAdapter::KEY_F9;
		mKeyMap[Qt::Key_F10] = osgGA::GUIEventAdapter::KEY_F10;
		mKeyMap[Qt::Key_F11] = osgGA::GUIEventAdapter::KEY_F11;
		mKeyMap[Qt::Key_F12] = osgGA::GUIEventAdapter::KEY_F12;
		mKeyMap[Qt::Key_F13] = osgGA::GUIEventAdapter::KEY_F13;
		mKeyMap[Qt::Key_F14] = osgGA::GUIEventAdapter::KEY_F14;
		mKeyMap[Qt::Key_F15] = osgGA::GUIEventAdapter::KEY_F15;
		mKeyMap[Qt::Key_F16] = osgGA::GUIEventAdapter::KEY_F16;
		mKeyMap[Qt::Key_F17] = osgGA::GUIEventAdapter::KEY_F17;
		mKeyMap[Qt::Key_F18] = osgGA::GUIEventAdapter::KEY_F18;
		mKeyMap[Qt::Key_F19] = osgGA::GUIEventAdapter::KEY_F19;
		mKeyMap[Qt::Key_F20] = osgGA::GUIEventAdapter::KEY_F20;

		mKeyMap[Qt::Key_hyphen] = '-';
		mKeyMap[Qt::Key_Equal] = '=';

		mKeyMap[Qt::Key_division] = osgGA::GUIEventAdapter::KEY_KP_Divide;
		mKeyMap[Qt::Key_multiply] = osgGA::GUIEventAdapter::KEY_KP_Multiply;
		mKeyMap[Qt::Key_Minus] = '-';
		mKeyMap[Qt::Key_Plus] = '+';
		//mKeyMap[Qt::Key_H              ] = osgGA::GUIEventAdapter::KEY_KP_Home;
		//mKeyMap[Qt::Key_                    ] = osgGA::GUIEventAdapter::KEY_KP_Up;
		//mKeyMap[92                    ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up;
		//mKeyMap[86                    ] = osgGA::GUIEventAdapter::KEY_KP_Left;
		//mKeyMap[87                    ] = osgGA::GUIEventAdapter::KEY_KP_Begin;
		//mKeyMap[88                    ] = osgGA::GUIEventAdapter::KEY_KP_Right;
		//mKeyMap[83                    ] = osgGA::GUIEventAdapter::KEY_KP_End;
		//mKeyMap[84                    ] = osgGA::GUIEventAdapter::KEY_KP_Down;
		//mKeyMap[85                    ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down;
		mKeyMap[Qt::Key_Insert] = osgGA::GUIEventAdapter::KEY_KP_Insert;
		//mKeyMap[Qt::Key_Delete        ] = osgGA::GUIEventAdapter::KEY_KP_Delete;
	}

	~QtKeyboardMap()
	{
	}

	int remapKey(QKeyEvent* event)
	{
		KeyMap::iterator itr = mKeyMap.find(event->key());
		if (itr == mKeyMap.end())
		{
			return int(*(event->text().toLatin1().data()));
		}
		else
			return itr->second;
	}

private:
	typedef std::map<unsigned int, int> KeyMap;
	KeyMap mKeyMap;
};

static QtKeyboardMap s_QtKeyboardMap;    



#if (QT_VERSION < QT_VERSION_CHECK(5, 2, 0))
#define GETDEVICEPIXELRATIO() 1.0
#else
#define GETDEVICEPIXELRATIO() devicePixelRatio()
#endif


QWidgetViewer::QWidgetViewer(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, bool forwardKeyEvents)
	: QGLWidget(parent, shareWidget, f),
	_gw(NULL),
	_touchEventsEnabled(false),
	_forwardKeyEvents(forwardKeyEvents)
{
	_devicePixelRatio = GETDEVICEPIXELRATIO();
}

QWidgetViewer::QWidgetViewer(QGLContext* context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f,
	bool forwardKeyEvents)
	: QGLWidget(context, parent, shareWidget, f),
	_gw(NULL),
	_touchEventsEnabled(false),
	_forwardKeyEvents(forwardKeyEvents)
{
	_devicePixelRatio = GETDEVICEPIXELRATIO();
}

QWidgetViewer::QWidgetViewer(const QGLFormat& format, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f,
	bool forwardKeyEvents)
	: QGLWidget(format, parent, shareWidget, f),
	_gw(NULL),
	_touchEventsEnabled(false),
	_forwardKeyEvents(forwardKeyEvents)
{
	_devicePixelRatio = GETDEVICEPIXELRATIO();
}

QWidgetViewer::~QWidgetViewer()
{
	// close GraphicsWindowQt1 and remove the reference to us
	if (_gw)
	{
		_gw->close();
		_gw->_widget = NULL;
		_gw = NULL;
	}
}

void QWidgetViewer::setTouchEventsEnabled(bool e)
{
#ifdef USE_GESTURES
	if (e == _touchEventsEnabled)
		return;

	_touchEventsEnabled = e;

	if (_touchEventsEnabled)
	{
		grabGesture(Qt::PinchGesture);
	}
	else
	{
		ungrabGesture(Qt::PinchGesture);
	}
#endif
}

void QWidgetViewer::processDeferredEvents()
{
	QQueue<QEvent::Type> deferredEventQueueCopy;
	{
		QMutexLocker lock(&_deferredEventQueueMutex);
		deferredEventQueueCopy = _deferredEventQueue;
		_eventCompressor.clear();
		_deferredEventQueue.clear();
	}

	while (!deferredEventQueueCopy.isEmpty())
	{
		QEvent event(deferredEventQueueCopy.dequeue());
		QGLWidget::event(&event);
	}
}

bool QWidgetViewer::event(QEvent* event)
{
#ifdef USE_GESTURES
	if (event->type() == QEvent::Gesture)
		return gestureEvent(static_cast<QGestureEvent*>(event));
#endif

	// QEvent::Hide
	//
	// workaround "Qt-workaround" that does glFinish before hiding the widget
	// (the Qt workaround was seen at least in Qt 4.6.3 and 4.7.0)
	//
	// Qt makes the context current, performs glFinish, and releases the context.
	// This makes the problem in OSG multithreaded environment as the context
	// is active in another thread, thus it can not be made current for the purpose
	// of glFinish in this thread.

	// QEvent::ParentChange
	//
	// Reparenting QWidgetViewer may create a new underlying window and a new GL context.
	// Qt will then call doneCurrent on the GL context about to be deleted. The thread
	// where old GL context was current has no longer current context to render to and
	// we cannot make new GL context current in this thread.

	// We workaround above problems by deferring execution of problematic event requests.
	// These events has to be enqueue and executed later in a main GUI thread (GUI operations
	// outside the main thread are not allowed) just before makeCurrent is called from the
	// right thread. The good place for doing that is right after swap in a swapBuffersImplementation.

	if (event->type() == QEvent::Hide)
	{
		// enqueue only the last of QEvent::Hide and QEvent::Show
		enqueueDeferredEvent(QEvent::Hide, QEvent::Show);
		return true;
	}
	else if (event->type() == QEvent::Show)
	{
		// enqueue only the last of QEvent::Show or QEvent::Hide
		enqueueDeferredEvent(QEvent::Show, QEvent::Hide);
		return true;
	}
	else if (event->type() == QEvent::ParentChange)
	{
		// enqueue only the last QEvent::ParentChange
		enqueueDeferredEvent(QEvent::ParentChange);
		return true;
	}

	// perform regular event handling
	return QGLWidget::event(event);
}

void QWidgetViewer::setKeyboardModifiers(QInputEvent* event)
{
	int modkey = event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier);
	unsigned int mask = 0;
	if (modkey & Qt::ShiftModifier) mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT;
	if (modkey & Qt::ControlModifier) mask |= osgGA::GUIEventAdapter::MODKEY_CTRL;
	if (modkey & Qt::AltModifier) mask |= osgGA::GUIEventAdapter::MODKEY_ALT;
	_gw->getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
}

void QWidgetViewer::resizeEvent(QResizeEvent* event)
{
	const QSize& size = event->size();

	int scaled_width = static_cast<int>(size.width()*_devicePixelRatio);
	int scaled_height = static_cast<int>(size.height()*_devicePixelRatio);
	_gw->resized(x(), y(), scaled_width, scaled_height);
	_gw->getEventQueue()->windowResize(x(), y(), scaled_width, scaled_height);
	_gw->requestRedraw();
}

void QWidgetViewer::moveEvent(QMoveEvent* event)
{

	//写上自己的事件处理
#if 1
	const QPoint& pos = event->pos();
	int scaled_width = static_cast<int>(width()*_devicePixelRatio);
	int scaled_height = static_cast<int>(height()*_devicePixelRatio);
	_gw->resized(pos.x(), pos.y(), scaled_width, scaled_height);
	_gw->getEventQueue()->windowResize(pos.x(), pos.y(), scaled_width, scaled_height);
#endif
}

void QWidgetViewer::glDraw()
{
	_gw->requestRedraw();
}

void QWidgetViewer::keyPressEvent(QKeyEvent* event)
{
	//写上自己的事件处理

#if 1
	setKeyboardModifiers(event);
	int value = s_QtKeyboardMap.remapKey(event);
	_gw->getEventQueue()->keyPress(value);

	// this passes the event to the regular Qt key event processing,
	// among others, it closes popup windows on ESC and forwards the event to the parent widgets
	if (_forwardKeyEvents)
		inherited::keyPressEvent(event);
#endif

}

void QWidgetViewer::keyReleaseEvent(QKeyEvent* event)
{
	//写上自己的事件处理

#if 1
if (event->isAutoRepeat())
	{
		event->ignore();
	}
	else
	{
		setKeyboardModifiers(event);
		int value = s_QtKeyboardMap.remapKey(event);
		_gw->getEventQueue()->keyRelease(value);
	}

	// this passes the event to the regular Qt key event processing,
	// among others, it closes popup windows on ESC and forwards the event to the parent widgets
	if (_forwardKeyEvents)
		inherited::keyReleaseEvent(event);
#endif
}

void QWidgetViewer::mousePressEvent(QMouseEvent* event)
{
	//写上自己的事件处理

#if 1
int button = 0;
	switch (event->button())
	{
	case Qt::LeftButton: button = 1; break;
	case Qt::MidButton: button = 2; break;
	case Qt::RightButton: button = 3; break;
	case Qt::NoButton: button = 0; break;
	default: button = 0; break;
	}
	setKeyboardModifiers(event);
	_gw->getEventQueue()->mouseButtonPress(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button);
#endif
}

void QWidgetViewer::mouseReleaseEvent(QMouseEvent* event)
{
	//写上自己的事件处理

#if 1
int button = 0;
	switch (event->button())
	{
	case Qt::LeftButton: button = 1; break;
	case Qt::MidButton: button = 2; break;
	case Qt::RightButton: button = 3; break;
	case Qt::NoButton: button = 0; break;
	default: button = 0; break;
	}
	setKeyboardModifiers(event);
	_gw->getEventQueue()->mouseButtonRelease(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button);
#endif
}

void QWidgetViewer::mouseDoubleClickEvent(QMouseEvent* event)
{

	//写上自己的事件处理

#if 1
	int button = 0;
	switch (event->button())
	{
	case Qt::LeftButton: button = 1; break;
	case Qt::MidButton: button = 2; break;
	case Qt::RightButton: button = 3; break;
	case Qt::NoButton: button = 0; break;
	default: button = 0; break;
	}
	setKeyboardModifiers(event);
	_gw->getEventQueue()->mouseDoubleButtonPress(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button);
#endif
}

void QWidgetViewer::mouseMoveEvent(QMouseEvent* event)
{
	//写上自己的事件处理

#if 1
	setKeyboardModifiers(event);
	_gw->getEventQueue()->mouseMotion(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio);
#endif
}

void QWidgetViewer::wheelEvent(QWheelEvent* event)
{
	//写上自己的事件处理

#if 1
	setKeyboardModifiers(event);
	_gw->getEventQueue()->mouseScroll(
		event->orientation() == Qt::Vertical ?
		(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) :
		(event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT));
#endif
}

#ifdef USE_GESTURES
static osgGA::GUIEventAdapter::TouchPhase translateQtGestureState(Qt::GestureState state)
{
	osgGA::GUIEventAdapter::TouchPhase touchPhase;
	switch (state)
	{
	case Qt::GestureStarted:
		touchPhase = osgGA::GUIEventAdapter::TOUCH_BEGAN;
		break;
	case Qt::GestureUpdated:
		touchPhase = osgGA::GUIEventAdapter::TOUCH_MOVED;
		break;
	case Qt::GestureFinished:
	case Qt::GestureCanceled:
		touchPhase = osgGA::GUIEventAdapter::TOUCH_ENDED;
		break;
	default:
		touchPhase = osgGA::GUIEventAdapter::TOUCH_UNKNOWN;
	};

	return touchPhase;
}
#endif


bool QWidgetViewer::gestureEvent(QGestureEvent* qevent)
{
#ifndef USE_GESTURES
	return false;
#else

	bool accept = false;

	if (QPinchGesture* pinch = static_cast<QPinchGesture *>(qevent->gesture(Qt::PinchGesture)))
	{
		const QPointF qcenterf = pinch->centerPoint();
		const float angle = pinch->totalRotationAngle();
		const float scale = pinch->totalScaleFactor();

		const QPoint pinchCenterQt = mapFromGlobal(qcenterf.toPoint());
		const osg::Vec2 pinchCenter(pinchCenterQt.x(), pinchCenterQt.y());

		//We don't have absolute positions of the two touches, only a scale and rotation
		//Hence we create pseudo-coordinates which are reasonable, and centered around the
		//real position
		const float radius = (width() + height()) / 4;
		const osg::Vec2 vector(scale*cos(angle)*radius, scale*sin(angle)*radius);
		const osg::Vec2 p0 = pinchCenter + vector;
		const osg::Vec2 p1 = pinchCenter - vector;

		osg::ref_ptr<osgGA::GUIEventAdapter> event = 0;
		const osgGA::GUIEventAdapter::TouchPhase touchPhase = translateQtGestureState(pinch->state());
		if (touchPhase == osgGA::GUIEventAdapter::TOUCH_BEGAN)
		{
			event = _gw->getEventQueue()->touchBegan(0, touchPhase, p0[0], p0[1]);
		}
		else if (touchPhase == osgGA::GUIEventAdapter::TOUCH_MOVED)
		{
			event = _gw->getEventQueue()->touchMoved(0, touchPhase, p0[0], p0[1]);
		}
		else
		{
			event = _gw->getEventQueue()->touchEnded(0, touchPhase, p0[0], p0[1], 1);
		}

		if (event)
		{
			event->addTouchPoint(1, touchPhase, p1[0], p1[1]);
			accept = true;
		}
	}

	if (accept)
		qevent->accept();

	return accept;
#endif
}







GraphicsWindowQt1::GraphicsWindowQt1(osg::GraphicsContext::Traits* traits, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
	: _realized(false)
{

	_widget = NULL;
	_traits = traits;
	init(parent, shareWidget, f);
}

GraphicsWindowQt1::GraphicsWindowQt1(QWidgetViewer* widget)
	: _realized(false)
{
	_widget = widget;
	_traits = _widget ? createTraits(_widget) : new osg::GraphicsContext::Traits;
	init(NULL, NULL, 0);
}

GraphicsWindowQt1::~GraphicsWindowQt1()
{
	close();

	// remove reference from QWidgetViewer
	if (_widget)
		_widget->_gw = NULL;
}

bool GraphicsWindowQt1::init(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
{
	// update _widget and parent by WindowData
	WindowData* windowData = _traits.get() ? dynamic_cast<WindowData*>(_traits->inheritedWindowData.get()) : 0;
	if (!_widget)
		_widget = windowData ? windowData->_widget : NULL;
	if (!parent)
		parent = windowData ? windowData->_parent : NULL;

	// create widget if it does not exist
	_ownsWidget = _widget == NULL;
	if (!_widget)
	{
		// shareWidget
		if (!shareWidget) {
			GraphicsWindowQt1* sharedContextQt = dynamic_cast<GraphicsWindowQt1*>(_traits->sharedContext.get());
			if (sharedContextQt)
				shareWidget = sharedContextQt->getGLWidget();
		}

		// WindowFlags
		Qt::WindowFlags flags = f | Qt::Window | Qt::CustomizeWindowHint;

		_traits->windowDecoration = false;   
		if (_traits->windowDecoration)
			flags |= Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowSystemMenuHint
#if (QT_VERSION_CHECK(4, 5, 0) <= QT_VERSION)
			| Qt::WindowCloseButtonHint
#endif
			;

		// create widget
		_widget = new QWidgetViewer(traits2qglFormat(_traits.get()), parent, shareWidget, flags);
	}

	// set widget name and position
	// (do not set it when we inherited the widget)
	if (_ownsWidget)
	{
		_widget->setWindowTitle(_traits->windowName.c_str());
		_widget->move(_traits->x, _traits->y);
		if (!_traits->supportsResize) _widget->setFixedSize(_traits->width, _traits->height);
		else _widget->resize(_traits->width, _traits->height);
	}

	// initialize widget properties
	_widget->setAutoBufferSwap(false);
	_widget->setMouseTracking(true);
	_widget->setFocusPolicy(Qt::WheelFocus);
	_widget->setGraphicsWindow(this);
	useCursor(_traits->useCursor);

	// initialize State
	setState(new osg::State);
	getState()->setGraphicsContext(this);

	// initialize contextID
	if (_traits.valid() && _traits->sharedContext.valid())
	{
		getState()->setContextID(_traits->sharedContext->getState()->getContextID());
		incrementContextIDUsageCount(getState()->getContextID());
	}
	else
	{
		getState()->setContextID(osg::GraphicsContext::createNewContextID());
	}

	// make sure the event queue has the correct window rectangle size and input range
	getEventQueue()->syncWindowRectangleWithGraphicsContext();

	return true;
}

QGLFormat GraphicsWindowQt1::traits2qglFormat(const osg::GraphicsContext::Traits* traits)
{
	QGLFormat format(QGLFormat::defaultFormat());

	format.setAlphaBufferSize(traits->alpha);
	format.setRedBufferSize(traits->red);
	format.setGreenBufferSize(traits->green);
	format.setBlueBufferSize(traits->blue);
	format.setDepthBufferSize(traits->depth);
	format.setStencilBufferSize(traits->stencil);
	format.setSampleBuffers(traits->sampleBuffers);
	format.setSamples(traits->samples);

	format.setAlpha(traits->alpha > 0);
	format.setDepth(traits->depth > 0);
	format.setStencil(traits->stencil > 0);
	format.setDoubleBuffer(traits->doubleBuffer);
	format.setSwapInterval(traits->vsync ? 1 : 0);
	format.setStereo(traits->quadBufferStereo ? 1 : 0);

	return format;
}

void GraphicsWindowQt1::qglFormat2traits(const QGLFormat& format, osg::GraphicsContext::Traits* traits)
{
	traits->red = format.redBufferSize();
	traits->green = format.greenBufferSize();
	traits->blue = format.blueBufferSize();
	traits->alpha = format.alpha() ? format.alphaBufferSize() : 0;
	traits->depth = format.depth() ? format.depthBufferSize() : 0;
	traits->stencil = format.stencil() ? format.stencilBufferSize() : 0;

	traits->sampleBuffers = format.sampleBuffers() ? 1 : 0;
	traits->samples = format.samples();

	traits->quadBufferStereo = format.stereo();
	traits->doubleBuffer = format.doubleBuffer();

	traits->vsync = format.swapInterval() >= 1;
}

osg::GraphicsContext::Traits* GraphicsWindowQt1::createTraits(const QGLWidget* widget)
{
	osg::GraphicsContext::Traits *traits = new osg::GraphicsContext::Traits;

	qglFormat2traits(widget->format(), traits);

	QRect r = widget->geometry();
	traits->x = r.x();
	traits->y = r.y();
	traits->width = r.width();
	traits->height = r.height();

	traits->windowName = widget->windowTitle().toLocal8Bit().data();
	Qt::WindowFlags f = widget->windowFlags();
	traits->windowDecoration = (f & Qt::WindowTitleHint) &&
		(f & Qt::WindowMinMaxButtonsHint) &&
		(f & Qt::WindowSystemMenuHint);
	QSizePolicy sp = widget->sizePolicy();
	traits->supportsResize = sp.horizontalPolicy() != QSizePolicy::Fixed ||
		sp.verticalPolicy() != QSizePolicy::Fixed;

	return traits;
}

bool GraphicsWindowQt1::setWindowRectangleImplementation(int x, int y, int width, int height)
{
	if (_widget == NULL)
		return false;

	_widget->setGeometry(x, y, width, height);
	return true;
}

void GraphicsWindowQt1::getWindowRectangle(int& x, int& y, int& width, int& height)
{
	if (_widget)
	{
		const QRect& geom = _widget->geometry();
		x = geom.x();
		y = geom.y();
		width = geom.width();
		height = geom.height();
	}
}

bool GraphicsWindowQt1::setWindowDecorationImplementation(bool windowDecoration)
{
	Qt::WindowFlags flags = Qt::Window | Qt::CustomizeWindowHint;                 //|Qt::WindowStaysOnTopHint;
	if(windowDecoration)
		flags |= Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowSystemMenuHint;
	_traits->windowDecoration = windowDecoration;

	if (_widget)
	{
		_widget->setWindowFlags(flags);

		return true;
	}

	return false;
}

bool GraphicsWindowQt1::getWindowDecoration() const
{
	return _traits->windowDecoration;
}

void GraphicsWindowQt1::grabFocus()
{
	if (_widget)
		_widget->setFocus(Qt::ActiveWindowFocusReason);
}

void GraphicsWindowQt1::grabFocusIfPointerInWindow()
{
	if (_widget->underMouse())
		_widget->setFocus(Qt::ActiveWindowFocusReason);
}

void GraphicsWindowQt1::raiseWindow()
{
	if (_widget)
		_widget->raise();
}

void GraphicsWindowQt1::setWindowName(const std::string& name)
{
	if (_widget)
		_widget->setWindowTitle(name.c_str());
}

std::string GraphicsWindowQt1::getWindowName()
{
	return _widget ? _widget->windowTitle().toStdString() : "";
}

void GraphicsWindowQt1::useCursor(bool cursorOn)
{
	if (_widget)
	{
		_traits->useCursor = cursorOn;
		if (!cursorOn) _widget->setCursor(Qt::BlankCursor);
		else _widget->setCursor(_currentCursor);
	}
}

void GraphicsWindowQt1::setCursor(MouseCursor cursor)
{
	if (cursor == InheritCursor && _widget)
	{
		_widget->unsetCursor();
	}

	switch (cursor)
	{
	case NoCursor: _currentCursor = Qt::BlankCursor; break;
	case RightArrowCursor: case LeftArrowCursor: _currentCursor = Qt::ArrowCursor; break;
	case InfoCursor: _currentCursor = Qt::SizeAllCursor; break;
	case DestroyCursor: _currentCursor = Qt::ForbiddenCursor; break;
	case HelpCursor: _currentCursor = Qt::WhatsThisCursor; break;
	case CycleCursor: _currentCursor = Qt::ForbiddenCursor; break;
	case SprayCursor: _currentCursor = Qt::SizeAllCursor; break;
	case WaitCursor: _currentCursor = Qt::WaitCursor; break;
	case TextCursor: _currentCursor = Qt::IBeamCursor; break;
	case CrosshairCursor: _currentCursor = Qt::CrossCursor; break;
	case HandCursor: _currentCursor = Qt::OpenHandCursor; break;
	case UpDownCursor: _currentCursor = Qt::SizeVerCursor; break;
	case LeftRightCursor: _currentCursor = Qt::SizeHorCursor; break;
	case TopSideCursor: case BottomSideCursor: _currentCursor = Qt::UpArrowCursor; break;
	case LeftSideCursor: case RightSideCursor: _currentCursor = Qt::SizeHorCursor; break;
	case TopLeftCorner: _currentCursor = Qt::SizeBDiagCursor; break;
	case TopRightCorner: _currentCursor = Qt::SizeFDiagCursor; break;
	case BottomRightCorner: _currentCursor = Qt::SizeBDiagCursor; break;
	case BottomLeftCorner: _currentCursor = Qt::SizeFDiagCursor; break;
	default: break;
	};
	if (_widget) _widget->setCursor(_currentCursor);
}

bool GraphicsWindowQt1::valid() const
{
	return _widget && _widget->isValid();
}

bool GraphicsWindowQt1::realizeImplementation()
{
	// save the current context
	// note: this will save only Qt-based contexts
	const QGLContext *savedContext = QGLContext::currentContext();

	// initialize GL context for the widget
	if (!valid())
		_widget->glInit();

	// make current
	_realized = true;
	bool result = makeCurrent();
	_realized = false;

	// fail if we do not have current context
	if (!result)
	{
		if (savedContext)
			const_cast<QGLContext*>(savedContext)->makeCurrent();

		OSG_WARN << "Window realize: Can make context current." << std::endl;
		return false;
	}

	_realized = true;

	// make sure the event queue has the correct window rectangle size and input range
	getEventQueue()->syncWindowRectangleWithGraphicsContext();

	// make this window's context not current
	// note: this must be done as we will probably make the context current from another thread
	//       and it is not allowed to have one context current in two threads
	if (!releaseContext())
		OSG_WARN << "Window realize: Can not release context." << std::endl;

	// restore previous context
	if (savedContext)
		const_cast<QGLContext*>(savedContext)->makeCurrent();

	return true;
}

bool GraphicsWindowQt1::isRealizedImplementation() const
{
	return _realized;
}

void GraphicsWindowQt1::closeImplementation()
{
	if (_widget)
		_widget->close();
	_realized = false;
}

void GraphicsWindowQt1::runOperations()
{
	// While in graphics thread this is last chance to do something useful before
	// graphics thread will execute its operations.
	if (_widget->getNumDeferredEvents() > 0)
		_widget->processDeferredEvents();

	if (QGLContext::currentContext() != _widget->context())
		_widget->makeCurrent();

	GraphicsWindow::runOperations();
}

bool GraphicsWindowQt1::makeCurrentImplementation()
{
	if (_widget->getNumDeferredEvents() > 0)
		_widget->processDeferredEvents();

	_widget->makeCurrent();

	return true;
}

bool GraphicsWindowQt1::releaseContextImplementation()
{
	_widget->doneCurrent();
	return true;
}

void GraphicsWindowQt1::swapBuffersImplementation()
{
	_widget->swapBuffers();

	// FIXME: the processDeferredEvents should really be executed in a GUI (main) thread context but
	// I couln't find any reliable way to do this. For now, lets hope non of *GUI thread only operations* will
	// be executed in a QGLWidget::event handler. On the other hand, calling GUI only operations in the
	// QGLWidget event handler is an indication of a Qt bug.
	if (_widget->getNumDeferredEvents() > 0)
		_widget->processDeferredEvents();

	// We need to call makeCurrent here to restore our previously current context
	// which may be changed by the processDeferredEvents function.
	if (QGLContext::currentContext() != _widget->context())
		_widget->makeCurrent();
}

void GraphicsWindowQt1::requestWarpPointer(float x, float y)
{
	if (_widget)
		QCursor::setPos(_widget->mapToGlobal(QPoint((int)x, (int)y)));
}

 

 

这里是怎么调用:

main.cpp


#include <QtWidgets/QApplication>
#include "osgInQt.h"
#include <QGridLayout>
#include <osgGA\StateSetManipulator>

#include "QWidgetViewer.h"

#pragma  comment(lib,"osgGAd.lib")

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);

	osgQt::initQtWindowingSystem();                //其实是调用了静态的 windowingSystemInterface 操作系统窗口接口
	osg::Group* sceneroot = new osg::Group;

	sceneroot->addChild(osgDB::readNodeFile("cow.osg"));
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
	viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
	viewer->addEventHandler(new osgViewer::StatsHandler);

	viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
	viewer->setSceneData(sceneroot);
	viewer->setCameraManipulator(new osgGA::TrackballManipulator);
	osgQt::setViewer(viewer.get());


	QWidgetViewer* glw = new QWidgetViewer();
	GraphicsWindowQt1* graphicswin = new GraphicsWindowQt1(glw);
	graphicswin->setCursor(GraphicsWindowQt1::MouseCursor::HandCursor);      //设置鼠标

	viewer->getCamera()->setViewport(new osg::Viewport(0, 0, glw->width(), glw->height()));
	viewer->getCamera()->setGraphicsContext(graphicswin);

	glw->setWindowTitle(QString::fromLocal8Bit("osg嵌入qt成功了"));
	glw->show();


	return a.exec();
}

示例资源下载:https://download.csdn.net/download/a_treasure/10634028(自己在各个虚函数里重写即可)

猜你喜欢

转载自blog.csdn.net/a_Treasure/article/details/82152245
今日推荐