OSG Qt Widget加载三维模型
graphicswindowqt.h
#ifndef GRAPHICSWINDOWQT_H #define GRAPHICSWINDOWQT_H #include <QGLWidget> #include <osgViewer/GraphicsWindow> #include <QMutex> #include <QEvent> #include <QQueue> #include <QSet> #include <QGLWidget> #include <QDragMoveEvent> #include <QDragEnterEvent> #include <QObject> class QInputEvent; class QGestureEvent; namespace osgViewer { class ViewerBase; } // forward declarations class GraphicsWindowQt; /// The function sets the WindowingSystem to Qt. void initQtWindowingSystem(); /** The function sets the viewer that will be used after entering * the Qt main loop (QCoreApplication::exec()). * * The function also initializes internal structures required for proper * scene rendering. * * The method must be called from main thread. */ void setViewer(osgViewer::ViewerBase *viewer); class GLWidget : public QGLWidget { Q_OBJECT typedef QGLWidget inherited; public: GLWidget(QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false); GLWidget(QGLContext* context, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false); GLWidget(const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false); virtual ~GLWidget(); inline void setGraphicsWindow(GraphicsWindowQt* gw) { _gw = gw; } inline GraphicsWindowQt* getGraphicsWindow() { return _gw; } inline const GraphicsWindowQt* 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: void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *event); void dropEvent(QDropEvent *event); signals: void signalEnter(QString str); void signalLeave(QString str); void signalReturnViewpoint(QString str); void signalMouseRelease(int button, float x, float y); void signalMouseMove(float x, float y); void signalDropEvent(QVariant var); void signalDelEvent(); void signalResizeEvent(int width, int height); public slots: void slotHandleEnd(bool bReset); 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 GraphicsWindowQt; GraphicsWindowQt* _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 GraphicsWindowQt : public QObject, public osgViewer::GraphicsWindow { Q_OBJECT public: GraphicsWindowQt(osg::GraphicsContext::Traits* traits, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0); GraphicsWindowQt(GLWidget* widget); virtual ~GraphicsWindowQt(); inline GLWidget* getGLWidget() { return _widget; } inline const GLWidget* getGLWidget() const { return _widget; } /// deprecated inline GLWidget* getGraphWidget() { return _widget; } /// deprecated inline const GLWidget* getGraphWidget() const { return _widget; } struct WindowData : public osg::Referenced { WindowData(GLWidget* widget = NULL, QWidget* parent = NULL) : _widget(widget), _parent(parent) {} GLWidget* _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); Q_SIGNALS: void moveOpenglContextToNewThread(QThread *newThread); public slots: void onMoveOpenglContextToNewThread(QThread *newThread); protected: friend class GLWidget; GLWidget* _widget; bool _ownsWidget; QCursor _currentCursor; bool _realized; }; #endif // GRAPHICSWINDOWQT_H
graphicswindowqt.cpp
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Wang Rui * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include "graphicswindowqt.h" #include <osg/DeleteHandler> //#include "GraphicsWindowQt.h" #include <osgViewer/ViewerBase> #include <QInputEvent> #include <QPointer> #include <QDebug> #include <QMimeData> #include <QThread> #include <QOpenGLContext> #include <QWidget> #include <QSurface> #include <QWindow> #if (QT_VERSION>=QT_VERSION_CHECK(4, 6, 0)) # define USE_GESTURES # include <QGestureEvent> # include <QGesture> #endif 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; /// The object responsible for the scene re-rendering. class HeartBeat : public QObject { public: int _timerId; osg::Timer _lastFrameStartTime; osg::observer_ptr< osgViewer::ViewerBase > _viewer; virtual ~HeartBeat(); void init(osgViewer::ViewerBase *viewer); void stopTimer(); void timerEvent(QTimerEvent *event); static HeartBeat* instance(); private: HeartBeat(); static QPointer<HeartBeat> heartBeat; }; QPointer<HeartBeat> HeartBeat::heartBeat; #if (QT_VERSION < QT_VERSION_CHECK(5, 2, 0)) #define GETDEVICEPIXELRATIO() 1.0 #else #define GETDEVICEPIXELRATIO() devicePixelRatio() #endif GLWidget::GLWidget(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, bool forwardKeyEvents) : QGLWidget(parent, shareWidget, f), _gw(NULL), _touchEventsEnabled(false), _forwardKeyEvents(forwardKeyEvents) { _devicePixelRatio = GETDEVICEPIXELRATIO(); setAttribute(Qt::WA_AcceptTouchEvents, true); setAcceptDrops(true); } GLWidget::GLWidget(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(); setAttribute(Qt::WA_AcceptTouchEvents, true); setAcceptDrops(true); } GLWidget::GLWidget(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(); setAttribute(Qt::WA_AcceptTouchEvents, true); setAcceptDrops(true); } GLWidget::~GLWidget() { // close GraphicsWindowQt and remove the reference to us if (_gw) { _gw->close(); _gw->_widget = NULL; _gw = NULL; } } void GLWidget::setTouchEventsEnabled(bool e) { #ifdef USE_GESTURES if (e == _touchEventsEnabled) return; _touchEventsEnabled = e; if (_touchEventsEnabled) { grabGesture(Qt::PinchGesture); } else { ungrabGesture(Qt::PinchGesture); } #endif } void GLWidget::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 GLWidget::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 GLWidget 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; } else if (event->type() == QEvent::Enter) { QString objectName = this->objectName(); emit signalEnter(objectName); //// // qDebug() << "Enter - "<< objectName; } else if (event->type() == QEvent::Leave) { QString objectName = this->objectName(); emit signalLeave(objectName); //// // qDebug() << "Leave - "<< objectName; } if (event->type() == QEvent::TouchBegin || event->type() == QEvent::TouchUpdate || event->type() == QEvent::TouchEnd) { QList<QTouchEvent::TouchPoint> pts = static_cast<QTouchEvent *>(event)->touchPoints(); if (pts.size() == 2) { const QTouchEvent::TouchPoint &pt1 = pts.first(); const QTouchEvent::TouchPoint &pt2 = pts.last(); osg::Vec2 pt1_now(pt1.pos().x(), pt1.pos().y()); osg::Vec2 pt2_now(pt2.pos().x(), pt2.pos().y()); osg::Vec2 pt1_last(pt1.startPos().x(), pt1.startPos().y()); osg::Vec2 pt2_last(pt2.startPos().x(), pt2.startPos().y()); float gap_now = (pt1_now - pt2_now).length(); float gap_last = (pt1_last - pt2_last).length(); if (fabs(gap_last - gap_now) >= 10.0) { _gw->getEventQueue()->mouseScroll( (gap_now - gap_last) > 0 ? osgGA::GUIEventAdapter::SCROLL_DOWN : osgGA::GUIEventAdapter::SCROLL_UP); } if (pt1.state() == Qt::TouchPointReleased || pt2.state() == Qt::TouchPointReleased) { } } } // perform regular event handling return QGLWidget::event(event); } void GLWidget::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 GLWidget::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(); emit signalResizeEvent(scaled_width, scaled_height); } void GLWidget::moveEvent(QMoveEvent* event) { 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); emit signalMouseMove(pos.x(), pos.y()); } void GLWidget::glDraw() { _gw->requestRedraw(); } void GLWidget::slotHandleEnd(bool bReset) { if (bReset) { //发送一个鼠标左键释放事件以便取消双击的状态 QMouseEvent event(QEvent::MouseButtonRelease, QPoint(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); mouseReleaseEvent(&event); } } void GLWidget::keyPressEvent(QKeyEvent* event) { setKeyboardModifiers(event); if (event->key() == Qt::Key_Space) { } else { 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); } void GLWidget::keyReleaseEvent(QKeyEvent* event) { if (event->isAutoRepeat()) { event->ignore(); } else { setKeyboardModifiers(event); if (event->key() == Qt::Key_Space) { QString objectName = this->objectName(); emit signalReturnViewpoint(objectName); } else if (event->key() == Qt::Key_Delete) { emit signalDelEvent(); } else { 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); } void GLWidget::mousePressEvent(QMouseEvent* event) { 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); } void GLWidget::mouseReleaseEvent(QMouseEvent* event) { int button = 0; switch (event->button()) { case Qt::LeftButton: { button = 1; emit signalMouseRelease(button, event->x()*_devicePixelRatio, event->y()*_devicePixelRatio); } break; case Qt::MidButton: button = 2; break; case Qt::RightButton: { button = 3; emit signalMouseRelease(button, event->x()*_devicePixelRatio, event->y()*_devicePixelRatio); } break; case Qt::NoButton: button = 0; break; default: button = 0; break; } setKeyboardModifiers(event); _gw->getEventQueue()->mouseButtonRelease(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button); } void GLWidget::mouseDoubleClickEvent(QMouseEvent* event) { 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); } void GLWidget::mouseMoveEvent(QMouseEvent* event) { double W = this->width(); double H = this->height(); if (this->parentWidget()) { double PW = this->parentWidget()->width(); double PH = this->parentWidget()->height(); if (event->pos().x() > 0 && event->pos().x() < PH && event->pos().y() > 0 && event->pos().y() < PH - PH / 10) { } else if (event->pos().x() > PH / 10 && event->pos().x() < PW && event->pos().y() > PH - PH / 10 && event->pos().y() < PH) { } } setKeyboardModifiers(event); _gw->getEventQueue()->mouseMotion(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio); emit signalMouseMove(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio); } void GLWidget::wheelEvent(QWheelEvent* event) { 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)); } #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 GLWidget::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 } void GLWidget::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("SimuFedData")) event->accept(); else event->ignore(); } void GLWidget::dragMoveEvent(QDragMoveEvent *event) { if (event->mimeData()->hasFormat("SimuFedData")) { event->setDropAction(Qt::MoveAction); event->accept(); } else event->ignore(); } void GLWidget::dropEvent(QDropEvent *event) { if (event->mimeData()->hasFormat("SimuFedData")) { QByteArray pieceData = event->mimeData()->data("SimuFedData"); QDataStream dataStream(&pieceData, QIODevice::ReadOnly); QPixmap pixmap; QString strParent; QString strType; QString strID; QVariant varData; dataStream >> pixmap >> strParent >> strType >> strID >> varData; QVariantList varList; varList.push_back(QVariant::fromValue(pixmap)); varList.push_back(QVariant(strParent)); varList.push_back(QVariant(strType)); varList.push_back(QVariant(strID)); QPointF pt = event->posF(); varList.push_back(QVariant(pt)); varList.push_back(varData); emit signalDropEvent(QVariant(varList)); } else event->ignore(); QGLWidget::dropEvent(event); } GraphicsWindowQt::GraphicsWindowQt(osg::GraphicsContext::Traits* traits, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f) : _realized(false) { _widget = NULL; _traits = traits; init(parent, shareWidget, f); } GraphicsWindowQt::GraphicsWindowQt(GLWidget* widget) : _realized(false) { _widget = widget; _traits = _widget ? createTraits(_widget) : new osg::GraphicsContext::Traits; init(NULL, NULL, 0); } GraphicsWindowQt::~GraphicsWindowQt() { close(); // remove reference from GLWidget if (_widget) _widget->_gw = NULL; } bool GraphicsWindowQt::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) { GraphicsWindowQt* sharedContextQt = dynamic_cast<GraphicsWindowQt*>(_traits->sharedContext.get()); if (sharedContextQt) shareWidget = sharedContextQt->getGLWidget(); } // WindowFlags Qt::WindowFlags flags = f | Qt::Window | Qt::CustomizeWindowHint; 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 GLWidget(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 GraphicsWindowQt::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 GraphicsWindowQt::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* GraphicsWindowQt::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 GraphicsWindowQt::setWindowRectangleImplementation(int x, int y, int width, int height) { if (_widget == NULL) return false; _widget->setGeometry(x, y, width, height); return true; } void GraphicsWindowQt::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 GraphicsWindowQt::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 GraphicsWindowQt::getWindowDecoration() const { return _traits->windowDecoration; } void GraphicsWindowQt::grabFocus() { if (_widget) _widget->setFocus(Qt::ActiveWindowFocusReason); } void GraphicsWindowQt::grabFocusIfPointerInWindow() { if (_widget->underMouse()) _widget->setFocus(Qt::ActiveWindowFocusReason); } void GraphicsWindowQt::raiseWindow() { if (_widget) _widget->raise(); } void GraphicsWindowQt::setWindowName(const std::string& name) { if (_widget) _widget->setWindowTitle(name.c_str()); } std::string GraphicsWindowQt::getWindowName() { return _widget ? _widget->windowTitle().toStdString() : ""; } void GraphicsWindowQt::useCursor(bool cursorOn) { if (_widget) { _traits->useCursor = cursorOn; if (!cursorOn) _widget->setCursor(Qt::BlankCursor); else _widget->setCursor(_currentCursor); } } void GraphicsWindowQt::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 GraphicsWindowQt::valid() const { return _widget && _widget->isValid(); } bool GraphicsWindowQt::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 GraphicsWindowQt::isRealizedImplementation() const { return _realized; } void GraphicsWindowQt::closeImplementation() { if (_widget) _widget->close(); _realized = false; } void GraphicsWindowQt::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 GraphicsWindowQt::makeCurrentImplementation() { if (_widget->getNumDeferredEvents() > 0) _widget->processDeferredEvents(); //QOpenGLContext* qglcx = _widget->context()->contextHandle(); //if (qglcx->thread() != QThread::currentThread()) //{ // if (!qglcx->thread()) // return true;//窗口关闭时 // //这是在另一个线程中做得,需要让主线程来movetothread,需要用信号槽机制告诉主线程 // _moveThread = new MoveThread; // connect(_moveThread, SIGNAL(moveThread(QThread*)), this, SLOT(onMoveOpenglContextToNewThread(QThread*)), Qt::BlockingQueuedConnection); // emit _moveThread->moveThread(QThread::currentThread()); // qglcx->makeCurrent(_widget->windowHandle()); //} //else { _widget->makeCurrent(); } return true; } bool GraphicsWindowQt::releaseContextImplementation() { _widget->doneCurrent(); return true; } void GraphicsWindowQt::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 GraphicsWindowQt::requestWarpPointer(float x, float y) { if (_widget) QCursor::setPos(_widget->mapToGlobal(QPoint((int)x, (int)y))); } void GraphicsWindowQt::onMoveOpenglContextToNewThread(QThread *newThread) { QOpenGLContext* qglcx = _widget->context()->contextHandle(); if (qglcx->thread() != newThread) { qglcx->doneCurrent(); qglcx->moveToThread(newThread); } //_mainWindow->onStartTimer(); } class QtWindowingSystem : public osg::GraphicsContext::WindowingSystemInterface { public: QtWindowingSystem() { OSG_INFO << "QtWindowingSystemInterface()" << std::endl; } ~QtWindowingSystem() { if (osg::Referenced::getDeleteHandler()) { osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); osg::Referenced::getDeleteHandler()->flushAll(); } } // Access the Qt windowing system through this singleton class. static QtWindowingSystem* getInterface() { static QtWindowingSystem* qtInterface = new QtWindowingSystem; return qtInterface; } // Return the number of screens present in the system virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& /*si*/) { OSG_WARN << "osgQt: getNumScreens() not implemented yet." << std::endl; return 0; } // Return the resolution of specified screen // (0,0) is returned if screen is unknown virtual void getScreenSettings(const osg::GraphicsContext::ScreenIdentifier& /*si*/, osg::GraphicsContext::ScreenSettings & /*resolution*/) { OSG_WARN << "osgQt: getScreenSettings() not implemented yet." << std::endl; } // Set the resolution for given screen virtual bool setScreenSettings(const osg::GraphicsContext::ScreenIdentifier& /*si*/, const osg::GraphicsContext::ScreenSettings & /*resolution*/) { OSG_WARN << "osgQt: setScreenSettings() not implemented yet." << std::endl; return false; } // Enumerates available resolutions virtual void enumerateScreenSettings(const osg::GraphicsContext::ScreenIdentifier& /*screenIdentifier*/, osg::GraphicsContext::ScreenSettingsList & /*resolution*/) { OSG_WARN << "osgQt: enumerateScreenSettings() not implemented yet." << std::endl; } // Create a graphics context with given traits virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits) { if (traits->pbuffer) { OSG_WARN << "osgQt: createGraphicsContext - pbuffer not implemented yet." << std::endl; return NULL; } else { osg::ref_ptr< GraphicsWindowQt > window = new GraphicsWindowQt(traits); if (window->valid()) return window.release(); else return NULL; } } private: // No implementation for these QtWindowingSystem(const QtWindowingSystem&); QtWindowingSystem& operator=(const QtWindowingSystem&); }; // declare C entry point for static compilation. void graphicswindow_Qt(void) { //osg::GraphicsContext::setWindowingSystemInterface(QtWindowingSystem::getInterface()); //osg::GraphicsContext::WindowingSystemInterface; //osg::GraphicsContext::WindowingSystemInterface; //QtWindowingSystem::getInterface() //static QtWindowingSystem* getInterface() { // static QtWindowingSystem* qtInterface = new QtWindowingSystem; // return qtInterface; //} //osg::GraphicsContext::WindowingSystemInterface = QtWindowingSystem::getInterface(); } void initQtWindowingSystem() { graphicswindow_Qt(); } void setViewer(osgViewer::ViewerBase *viewer) { HeartBeat::instance()->init(viewer); } /// Constructor. Must be called from main thread. HeartBeat::HeartBeat() : _timerId(0) { } /// Destructor. Must be called from main thread. HeartBeat::~HeartBeat() { stopTimer(); } HeartBeat* HeartBeat::instance() { if (!heartBeat) { heartBeat = new HeartBeat(); } return heartBeat; } void HeartBeat::stopTimer() { if (_timerId != 0) { killTimer(_timerId); _timerId = 0; } } /// Initializes the loop for viewer. Must be called from main thread. void HeartBeat::init(osgViewer::ViewerBase *viewer) { if (_viewer == viewer) return; stopTimer(); _viewer = viewer; if (viewer) { _timerId = startTimer(0); _lastFrameStartTime.setStartTick(0); } } void HeartBeat::timerEvent(QTimerEvent * /*event*/) { osg::ref_ptr< osgViewer::ViewerBase > viewer; if (!_viewer.lock(viewer)) { // viewer has been deleted -> stop timer stopTimer(); return; } // limit the frame rate if (viewer->getRunMaxFrameRate() > 0.0) { double dt = _lastFrameStartTime.time_s(); double minFrameTime = 1.0 / viewer->getRunMaxFrameRate(); if (dt < minFrameTime) OpenThreads::Thread::microSleep(static_cast<unsigned int>(1000000.0*(minFrameTime - dt))); } else { // avoid excessive CPU loading when no frame is required in ON_DEMAND mode if (viewer->getRunFrameScheme() == osgViewer::ViewerBase::ON_DEMAND) { double dt = _lastFrameStartTime.time_s(); if (dt < 0.01) OpenThreads::Thread::microSleep(static_cast<unsigned int>(1000000.0*(0.01 - dt))); } // record start frame time _lastFrameStartTime.setStartTick(); // make frame if (viewer->getRunFrameScheme() == osgViewer::ViewerBase::ON_DEMAND) { if (viewer->checkNeedToDoFrame()) { viewer->frame(); } } else { viewer->frame(); } } }
vcqtosgwidget.h
#ifndef VCQTOSGWIDGET_H #define VCQTOSGWIDGET_H #include <QObject> #include <QString> #include <QDebug> #include <QtWidgets/QMainWindow> #include "ui_QtGuiOSG2.h" #include <osg/Geode> #include <osg/Geometry> #include <osg/LineWidth> #include <osgViewer/Viewer> #include <osgDB/ReadFile> #include <osgDB/WriteFile> #include <osgViewer/ViewerEventHandlers> #include <osg/Geode> #include <osg/Geometry> #include <osg/LineWidth> #include <osgViewer/Viewer> #include <osgDB/ReadFile> #include <osgViewer/Viewer> #include <osgDB/ReadFile> #include <osgDB/WriteFile> #include <osgViewer/ViewerEventHandlers> #include <osgViewer/CompositeViewer> #include <osg/PositionAttitudeTransform> #include <osg/MatrixTransform> #include <osgFX/Scribe> #include <osgParticle/PrecipitationEffect> #include <osg/NodeCallback> #include <osg/DrawPixels> #include <osg/ComputeBoundsVisitor> #include <osgGA/TrackballManipulator> class VCQtOsgWidget : public QMainWindow { Q_OBJECT public: VCQtOsgWidget(QWidget *parent = Q_NULLPTR); private: void init(); osg::LightSource* createLight(); private slots: void slotTimeUpdate(); private: //Ui::QtGuiOSGClass ui; Ui::QtGuiOSG2Class ui; osgViewer::Viewer* _viewer = nullptr; unsigned int _screenW, _screenH; QTimer* _timer; }; #endif // VCQTOSGWIDGET_H
vcqtosgwidget.cpp
#include "vcqtosgwidget.h" #include <osg/GraphicsContext> #include "graphicswindowqt.h" #include <QTimer> VCQtOsgWidget::VCQtOsgWidget(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); init(); } void VCQtOsgWidget::init() { osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface(); if (!wsi) { osg::notify(osg::NOTICE) << "Error, no WindowSystemInterface available, cannot create windows." << std::endl; return; } wsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), _screenW, _screenH); osg::DisplaySettings* ds = osg::DisplaySettings::instance().get(); osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; traits->x = 0; traits->y = 0; traits->width = _screenW; traits->height = _screenH; traits->windowDecoration = false; traits->doubleBuffer = true; traits->sharedContext = 0; traits->alpha = ds->getMinimumNumAlphaBits(); traits->stencil = ds->getMinimumNumStencilBits(); traits->sampleBuffers = ds->getMultiSamples(); traits->samples = 16; traits->vsync = false; osg::GraphicsContext* gc = new GraphicsWindowQt(traits.get()); osg::ref_ptr<osg::Camera> camera = new osg::Camera; camera->setGraphicsContext(gc); camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); camera->setViewport(new osg::Viewport(0, 0, _screenW, _screenH)); camera->setClearColor(osg::Vec4(128.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0, 0.8)); camera->setProjectionMatrixAsPerspective(30.0, static_cast<double>(_screenW) / static_cast<double>(_screenH), 1.0, 10000.0); _viewer = new osgViewer::Viewer; osg::ref_ptr<osg::Group> root = new osg::Group; //注意:这两句话的先后顺序 先添加模型在添加相机 //root->addChild(osgDB::readNodeFile("cow.osgt")); root->addChild(osgDB::readNodeFile("D:\\参考手册\\BIM\\osg\\library.OSGB")); root->addChild(createLight()); _viewer->setCamera(camera);//这两句话的先后顺序 _viewer->setSceneData(root); _viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded); _viewer->setCameraManipulator(new osgGA::TrackballManipulator); _viewer->addEventHandler(new osgViewer::WindowSizeHandler()); GraphicsWindowQt* gcQT = dynamic_cast<GraphicsWindowQt*>(gc); if (gcQT) { QWidget *pWgt = gcQT->getGLWidget(); //ui.verticalLayout->addWidget(pWgt); ui.verticalLayout->addWidget(pWgt); } _timer = new QTimer; connect(_timer, SIGNAL(timeout()), this, SLOT(slotTimeUpdate())); _timer->start(5); } osg::LightSource* VCQtOsgWidget::createLight() { osg::LightSource* ls = new osg::LightSource; osg::ref_ptr<osg::Light> light = new osg::Light; light->setLightNum(0); light->setPosition(osg::Vec4(0.0, -3.0, 0.0, 0.0)); light->setDirection(osg::Vec3(0.0, -1.0, 0.0)); light->setDiffuse(osg::Vec4(0.0, 0.0, 1.0, 1.0)); ls->setLight(light); return ls; } void VCQtOsgWidget::slotTimeUpdate() { _viewer->frame(); }
main.cpp
#include "vcqtosgwidget.h" #include <QtWidgets/QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); //OSG_QT_Test2019061601 w; //w.show(); VCQtOsgWidget vc_w; vc_w.show(); return a.exec(); }
QQ 3087438119