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 = , bool forwardKeyEvents = false);
  GLWidget(QGLContext* context, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = , bool forwardKeyEvents = false);
  GLWidget(const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = , 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 = );
  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() == ) {
      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) > ? 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 = ;
  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 = ;
  switch (event->button()) {
  case Qt::LeftButton: button = ; break;
  case Qt::MidButton: button = ; break;
  case Qt::RightButton: button = ; break;
  case Qt::NoButton: button = ; break;
  default: button = ; break;
  }
  setKeyboardModifiers(event);
  _gw->getEventQueue()->mouseButtonPress(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button);
} void GLWidget::mouseReleaseEvent(QMouseEvent* event) {
  int button = ;
  switch (event->button()) {
  case Qt::LeftButton:
  {
    button = ;
    emit signalMouseRelease(button, event->x()*_devicePixelRatio, event->y()*_devicePixelRatio);
  }
  break;   case Qt::MidButton: button = ; break;
  case Qt::RightButton:
  {
    button = ;
    emit signalMouseRelease(button, event->x()*_devicePixelRatio, event->y()*_devicePixelRatio);
  }
  break;   case Qt::NoButton: button = ; break;
  default: button = ; break;
  }
  setKeyboardModifiers(event);
  _gw->getEventQueue()->mouseButtonRelease(event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button);
} void GLWidget::mouseDoubleClickEvent(QMouseEvent* event) {
  int button = ;
  switch (event->button()) {
  case Qt::LeftButton: button = ; break;
  case Qt::MidButton: button = ; break;
  case Qt::RightButton: button = ; break;
  case Qt::NoButton: button = ; break;
  default: button = ; 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() > && event->pos().x() < PH && event->pos().y() > && event->pos().y() < PH - PH / ) {     }
    else if (event->pos().x() > PH / && event->pos().x() < PW && event->pos().y() > PH - PH / && 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() > ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) :
    (event->delta() > ? 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()) / ;
    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 = ;
    const osgGA::GUIEventAdapter::TouchPhase touchPhase = translateQtGestureState(pinch->state());
    if (touchPhase == osgGA::GUIEventAdapter::TOUCH_BEGAN) {
      event = _gw->getEventQueue()->touchBegan(, touchPhase, p0[], p0[]);
    }
    else if (touchPhase == osgGA::GUIEventAdapter::TOUCH_MOVED) {
      event = _gw->getEventQueue()->touchMoved(, touchPhase, p0[], p0[]);
    }
    else {
      event = _gw->getEventQueue()->touchEnded(, touchPhase, p0[], p0[], );
    }     if (event) {
      event->addTouchPoint(, touchPhase, p1[], p1[]);
      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, );
} 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()) : ;
  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 > );
  format.setDepth(traits->depth > );
  format.setStencil(traits->stencil > );
  format.setDoubleBuffer(traits->doubleBuffer);
  format.setSwapInterval(traits->vsync ? : );
  format.setStereo(traits->quadBufferStereo ? : );   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() : ;
  traits->depth = format.depth() ? format.depthBufferSize() : ;
  traits->stencil = format.stencil() ? format.stencilBufferSize() : ;   traits->sampleBuffers = format.sampleBuffers() ? : ;
  traits->samples = format.samples();   traits->quadBufferStereo = format.stereo();
  traits->doubleBuffer = format.doubleBuffer();   traits->vsync = format.swapInterval() >= ;
} 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() > )
    _widget->processDeferredEvents();   if (QGLContext::currentContext() != _widget->context())
    _widget->makeCurrent();   GraphicsWindow::runOperations();
} bool GraphicsWindowQt::makeCurrentImplementation() {
  if (_widget->getNumDeferredEvents() > )
    _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() > )
    _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();
      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 ;
  }   // 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() {
} /// 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 != ) {
    killTimer(_timerId);
    _timerId = ;
  }
} /// 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();
    _lastFrameStartTime.setStartTick();
  }
} 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(), _screenW, _screenH);   osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();   osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
  traits->x = ;
  traits->y = ;
  traits->width = _screenW;
  traits->height = _screenH;
  traits->windowDecoration = false;
  traits->doubleBuffer = true;
  traits->sharedContext = ;   traits->alpha = ds->getMinimumNumAlphaBits();
  traits->stencil = ds->getMinimumNumStencilBits();
  traits->sampleBuffers = ds->getMultiSamples();   traits->samples = ;
  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(, , _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();
} osg::LightSource* VCQtOsgWidget::createLight() {
  osg::LightSource* ls = new osg::LightSource;   osg::ref_ptr<osg::Light> light = new osg::Light;
  light->setLightNum();
  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();
}

OSG Qt Widget加载三维模型的更多相关文章

  1. cesium js学习一加载三维模型【转】

    http://blog.csdn.net/tangyajun_168/article/details/50936698 最近项目中用到室外三维模型与室内三维地图交互,室外三维模型的加载我们采用了ces ...

  2. World Wind Java开发之十五——加载三维模型(转)

    之前的一篇博客是关于加载粗三维模型的,见http://blog.csdn.net/giser_whu/article/details/43452703,这个地方还存在着不能加载纹理的问题,一直没呢解决 ...

  3. Qt tableview加载数据

    Qt tableview加载数据 //把数据加载到tableView void ImportData::loadDataInTableView() { ) { if (pageNum>stude ...

  4. cesium初探之加载三维模型

    项目需要用到二三维地图切换,本来准备研究ArcGIS js for Web 3d,但考虑到版权的问题,决定试着用cesium来做,于是花了2天时间抱着试试看的心态把cesium从环境配置到加载三维模型 ...

  5. Qt之加载QSS文件

    简述 Qt中关于样式的使用很常见,为了降低耦合性(与逻辑代码分离),我们通常会定义一个QSS文件,然后编写各种部件(例如:QLable.QLineEdit.QPushButton)的样式,最后使用QA ...

  6. Qt 动态加载DLL 常见错误有哪些?

    1. dll 路径不对,比如 IE 中 2. 依赖库缺失,会报错找不到指定模块 注意: qt 的 qlibrary 只能加载 标准 C 函数

  7. [转][osg]关于PagedLOD 加载卸载机制

    你的PagedLOD 为什么没有卸载 转自:http://bbs.osgchina.org/forum.php?mod=viewthread&tid=7612&highlight=Pa ...

  8. qt资源加载出错

    -1: error: No rule to make target '../InteractivePlayer/style.qss', needed by 'debug/qrc_res.cpp'.  ...

  9. [osg][osgearth]osg的分页加载,代码和结构图

    DatabasePager加载数据的过程: 多线程 使用DatabasePager加载数据的流程: 左侧的图框表示数据的检索和输入, 中间的白色框表示用于数据存储的内存空间,而右边的图框表示存储数据的 ...

随机推荐

  1. maven的一些命令以及说明 ——1

    mvn  compile  :  编译源文件 mvn  test-compile : 编译Junit测试文件 mvn test : 运行junit测试文件 mvn package : 编译 + 测试 ...

  2. pandas处理json脱坑(二)--jsonError: Expecting ',' delimiter: line 1 column 2674

    Expecting ',' delimiter: line 1 column 2674 json_dict = json.loads(row[json_columns].replace("' ...

  3. 【51nod 1340】地铁环线

    题目 有一个地铁环线,环线中有N个站台,标号为0,1,2,...,N-1.这个环线是单行线,一共由N条有向边构成,即从0到1,1到2,..k到k+1,...,N-2到N-1,N-1到0各有一条边.定义 ...

  4. oracle数据库GROUP BY 子句

    1.GROUP BY子句 在SELECT 列表中所有未包含在组函数中的列都应该包含在GROUP BY 子句中. 如下: SELECT deptno,AVG(sal) from emp GROUP BY ...

  5. python 比较运算符

    x == y x < y x <= y x >= y x  != y x is y x is not y x in y x not in y >>> "f ...

  6. 「CF484E」Sign on Fence「整体二分」「线段树」

    题意 给定一个长度为\(n\)的正整数序列,第\(i\)个数为\(h_i\),\(m\)个询问,每次询问\((l, r, w)\),为\([l, r]\)所有长度为\(w\)的子区间最小值的最大值.( ...

  7. 【概率论】3-8:随机变量函数(Functions of a Random Variable)

    title: [概率论]3-8:随机变量函数(Functions of a Random Variable) categories: Mathematic Probability keywords: ...

  8. 又见回文 (SDUT 2560)

    Problem Description "回文串"是一个正读和反读都一样的字符串,比如"level"或者"noon"等等就是回文串.现在呢, ...

  9. 如何在vue中使用svg

    1.安装依赖 npm install svg-sprite-loader --save-dev 2.在config文件中配置    const path = require('path'); func ...

  10. Kafka详细原理

    Kafka Kafka是最初由Linkedin公司开发,是一个分布式.支持分区的(partition).多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实 ...