zoukankan      html  css  js  c++  java
  • 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();
    }

  • 相关阅读:
    linux sysfs (2)
    微软——助您启动云的力量网络虚拟盛会
    Windows Azure入门教学系列 全面更新啦!
    与Advanced Telemetry创始人兼 CTO, Tom Naylor的访谈
    Windows Azure AppFabric概述
    Windows Azure Extra Small Instances Public Beta版本发布
    DataMarket 一月内容更新
    和Steve, Wade 一起学习如何使用Windows Azure Startup Tasks
    现实世界的Windows Azure:与eCraft的 Nicklas Andersson(CTO),Peter Löfgren(项目经理)以及Jörgen Westerling(CCO)的访谈
    正确使用Windows Azure 中的VM Role
  • 原文地址:https://www.cnblogs.com/herd/p/11032714.html
Copyright © 2011-2022 走看看