查看: 905|回复: 2

【已解决】自定义的trackball_manipulator没有连续变化效果

[复制链接]

该用户从未签到

发表于 2015-11-11 19:42:24 | 显示全部楼层 |阅读模式
本帖最后由 江湖贫侠 于 2015-11-12 10:24 编辑

我想重载trackballManipulator的handle函数,自己定义按键消息,比如中键旋转场景。但发现当鼠标拖动时,camera只能变化一下,必须再点一次才能再转动一下。
代码如下,不知道问题出在哪里?

  1.         class customize_trackball_manipulator : public osgGA::TrackballManipulator
  2.                 {
  3.                 public:
  4.                         enum event_type_idx{ ROTATION, SCALE, TRANSLATION, NOTHING };
  5.                         typedef osgGA::TrackballManipulator inherited;

  6.                         customize_trackball_manipulator(int flags = DEFAULT_SETTINGS) :inherited(flags){ setVerticalAxisFixed(false); }
  7.                         customize_trackball_manipulator(const customize_trackball_manipulator& om,
  8.                                 const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
  9.                                 : inherited(om, copyOp) {}
  10.                         META_Object(osgGA::osgGA, customize_trackball_manipulator);
  11.                 protected:
  12.                         virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);

  13.                         virtual bool handleMouseMove(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);

  14.                 private:
  15.                         bool is_rotation_with_modkey(const osgGA::GUIEventAdapter& ea);
  16.                         bool is_rotation_without_modkey(const osgGA::GUIEventAdapter& ea);
  17.                         bool is_translation_with_modkey(const osgGA::GUIEventAdapter & ea);
  18.                         bool is_scale_with_modkey(const osgGA::GUIEventAdapter & ea);
  19.                         bool is_scale_without_modkey(const osgGA::GUIEventAdapter & ea);
  20.                 };
复制代码


实现如下:
  1. bool customize_trackball_manipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
  2.                 {
  3.                         using namespace osgGA;
  4.                         switch (ea.getEventType())
  5.                         {
  6.                         case GUIEventAdapter::FRAME:
  7.                                 return handleFrame(ea, us);

  8.                         case GUIEventAdapter::RESIZE:
  9.                                 return handleResize(ea, us);

  10.                         default:
  11.                                 break;
  12.                         }

  13.                         if (ea.getHandled())
  14.                                 return false;

  15.                         if (ea.getEventType() == GUIEventAdapter::SCROLL){
  16.                                 if (_flags & PROCESS_MOUSE_WHEEL)
  17.                                         return handleMouseWheel(ea, us);
  18.                                 else
  19.                                         return false;
  20.                         }
  21.                         return handleMouseMove(ea, us);
  22.                 }

  23.                 bool customize_trackball_manipulator::handleMouseMove(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
  24.                 {
  25.                         float dx = ea.getX() - _mouseCenterX;
  26.                         float dy = ea.getY() - _mouseCenterY;

  27.                         if (dx == 0.f && dy == 0.f)
  28.                                 return false;

  29.                         addMouseEvent(ea);
  30.                         centerMousePointer(ea, us);

  31.                         if (is_scale_with_modkey(ea))
  32.                         {
  33.                                 if (dx > 0)
  34.                                 {
  35.                                         zoomModel(_wheelZoomFactor, true);
  36.                                         us.requestRedraw();
  37.                                         us.requestContinuousUpdate(isAnimating() || _thrown);
  38.                                         return true;
  39.                                 }
  40.                                 else{
  41.                                         zoomModel(-_wheelZoomFactor, true);
  42.                                         us.requestRedraw();
  43.                                         us.requestContinuousUpdate(isAnimating() || _thrown);
  44.                                         return true;
  45.                                 }
  46.                         }

  47.                         if (is_rotation_with_modkey(ea) || is_rotation_without_modkey(ea))
  48.                         {
  49.                                 if (getVerticalAxisFixed())
  50.                                         rotateWithFixedVertical(dx, dy);
  51.                                 else
  52.                                         rotateTrackball(0.f, 0.f, dx, dy, 1.f);
  53.                                 us.requestRedraw();
  54.                                 us.requestContinuousUpdate(isAnimating() || _thrown);
  55.                                 return true;
  56.                         }

  57.                         if (is_translation_with_modkey(ea))
  58.                         {
  59.                                 double eventTimeDelta = _ga_t0->getTime() - _ga_t1->getTime();
  60.                                 if (eventTimeDelta < 0.)
  61.                                 {
  62.                                         OSG_WARN << "Manipulator warning: eventTimeDelta = " << eventTimeDelta << std::endl;
  63.                                         eventTimeDelta = 0.;
  64.                                 }
  65.                                 float scale = -0.3f * _distance * getThrowScale(eventTimeDelta);
  66.                                 panModel(dx*scale, dy*scale);
  67.                                 return true;
  68.                         }

  69.                         return false;
  70.                 }
复制代码

该用户从未签到

 楼主| 发表于 2015-11-11 23:55:01 | 显示全部楼层
问题解决,可以直接用performMovementLeftMouseButton等接口。

  1. class customize_manipulator : public osgGA::TrackballManipulator
  2. {
  3. public:
  4.         typedef osgGA::TrackballManipulator inherited;

  5. public:
  6.         customize_manipulator(int flags = DEFAULT_SETTINGS):osgGA::TrackballManipulator(flags){}
  7.         customize_manipulator(const customize_manipulator& tm,
  8.                 const osg::CopyOp& copyOp = osg::CopyOp::SHALLOW_COPY)
  9.         :osgGA::TrackballManipulator(tm, copyOp){}

  10.         META_Object(osgGA, customize_manipulator);
  11. protected:
  12.         virtual bool performMovementLeftMouseButton(const double eventTimeDelta, const double dx, const double dy)
  13.         {
  14.                 return false;
  15.         }
  16.         virtual bool performMovementMiddleMouseButton(const double eventTimeDelta, const double dx, const double dy)
  17.         {
  18.                 if(_ga_t1->getModKeyMask() == 0){ //rotation
  19.                         if (getVerticalAxisFixed())
  20.                                 rotateWithFixedVertical(dx, dy);
  21.                         else
  22.                                 rotateTrackball(_ga_t0->getXnormalized(), _ga_t0->getYnormalized(),
  23.                                         _ga_t1->getXnormalized(), _ga_t1->getYnormalized(),
  24.                                         getThrowScale(eventTimeDelta));
  25.                         return true;
  26.                 }
  27.                 if (_ga_t1->getModKeyMask() == osgGA::GUIEventAdapter::ModKeyMask::MODKEY_LEFT_ALT) // translation
  28.                 {
  29.                         float scale = -0.3f * _distance * getThrowScale(eventTimeDelta);
  30.                         panModel(dx*scale, dy*scale);
  31.                         return true;
  32.                 }
  33.                 return false;
  34.         }
  35.         virtual bool performMovementRightMouseButton(const double eventTimeDelta, const double dx, const double dy)
  36.         {
  37.                 if (_ga_t1->getModKeyMask() == osgGA::GUIEventAdapter::ModKeyMask::MODKEY_LEFT_CTRL) { // rotation
  38.                         if (getVerticalAxisFixed())
  39.                                 rotateWithFixedVertical(dx, dy);
  40.                         else
  41.                                 rotateTrackball(_ga_t0->getXnormalized(), _ga_t0->getYnormalized(),
  42.                                         _ga_t1->getXnormalized(), _ga_t1->getYnormalized(),
  43.                                         getThrowScale(eventTimeDelta));
  44.                         return true;
  45.                 }

  46.                 if (_ga_t1->getModKeyMask() == osgGA::GUIEventAdapter::ModKeyMask::MODKEY_LEFT_ALT) //translation
  47.                 {
  48.                         float scale = -0.3f * _distance * getThrowScale(eventTimeDelta);
  49.                         panModel(dx*scale, dy*scale);
  50.                         return true;
  51.                 }
  52.                 if (_ga_t1->getModKeyMask() == osgGA::GUIEventAdapter::ModKeyMask::MODKEY_LEFT_SHIFT) { // scale
  53.                         zoomModel(dy * getThrowScale(eventTimeDelta), true);
  54.                         return true;
  55.                 }
  56.                 return false;
  57.         }

  58. };
复制代码

该用户从未签到

 楼主| 发表于 2015-11-12 10:24:18 | 显示全部楼层
事实上,这个问题的根本原因是,我程序中qt和osg结合的过程中,消息映射没做好。
我把代码放出来,避免后来者再走弯路。
  1. void OSGWidget::setKeyboardModifiers(QInputEvent* event)
  2.         {
  3.                 int modkey = event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier);
  4.                 unsigned int mask = 0;
  5.                 if (modkey & Qt::ShiftModifier) mask |= osgGA::GUIEventAdapter::MODKEY_LEFT_SHIFT;
  6.                 if (modkey & Qt::ControlModifier) mask |= osgGA::GUIEventAdapter::MODKEY_LEFT_CTRL;
  7.                 if (modkey & Qt::AltModifier) mask |= osgGA::GUIEventAdapter::MODKEY_LEFT_ALT;
  8.                 this->getEventQueue()->getCurrentEventState()->setModKeyMask(mask);
  9.         }

  10.         void OSGWidget::keyPressEvent(QKeyEvent* event)
  11.         {
  12.                 setKeyboardModifiers(event);
  13.                 this->getEventQueue()->keyPress((osgGA::GUIEventAdapter::KeySymbol) *(event->text().toLatin1().data()));
  14.         }

  15.         void OSGWidget::keyReleaseEvent(QKeyEvent* event)
  16.         {
  17.                 setKeyboardModifiers(event);
  18.                 this->getEventQueue()->keyRelease((osgGA::GUIEventAdapter::KeySymbol) *(event->text().toLatin1().data()));
  19.         }

  20.         void OSGWidget::mouseMoveEvent(QMouseEvent* event)
  21.         {
  22.                 setKeyboardModifiers(event);
  23.                 this->getEventQueue()->mouseMotion(event->x(), event->y());
  24.         }

  25.         void OSGWidget::mousePressEvent(QMouseEvent* event)
  26.         {
  27.                 int button = 0;
  28.                 switch (event->button())
  29.                 {
  30.                 case Qt::LeftButton: button = 1; break;
  31.                 case Qt::MidButton: button = 2; break;
  32.                 case Qt::RightButton: button = 3; break;
  33.                 case Qt::NoButton: button = 0; break;
  34.                 default: button = 0; break;
  35.                 }
  36.                 setKeyboardModifiers(event);
  37.                 this->getEventQueue()->mouseButtonPress(event->x(), event->y(), button);
  38.         }

  39.         void OSGWidget::initMenu()
  40.         {
  41.         }

  42.         void OSGWidget::mouseReleaseEvent(QMouseEvent* event)
  43.         {
  44.                 int button = 0;
  45.                 switch (event->button())
  46.                 {
  47.                 case Qt::LeftButton: button = 1; break;
  48.                 case Qt::MidButton: button = 2; break;
  49.                 case Qt::RightButton: button = 3; break;
  50.                 case Qt::NoButton: button = 0; break;
  51.                 default: button = 0; break;
  52.                 }
  53.                 setKeyboardModifiers(event);
  54.                 this->getEventQueue()->mouseButtonRelease(event->x(), event->y(), button);
  55.         }

  56.         void OSGWidget::wheelEvent(QWheelEvent* event)
  57.         {
  58.                 setKeyboardModifiers(event);
  59.                 this->getEventQueue()->mouseScroll(
  60.                         event->delta() > 0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN);
  61.         }

  62.         void OSGWidget::mouseDoubleClickEvent(QMouseEvent *event)
  63.         {
  64.                 int button = 0;
  65.                 switch (event->button())
  66.                 {
  67.                 case Qt::LeftButton: button = 1; break;
  68.                 case Qt::MidButton: button = 2; break;
  69.                 case Qt::RightButton: button = 3; break;
  70.                 case Qt::NoButton: button = 0; break;
  71.                 default: button = 0; break;
  72.                 }
  73.                 setKeyboardModifiers(event);
  74.                 this->getEventQueue()->mouseDoubleButtonPress(event->x(), event->y(), button);
  75.         }

  76.         void OSGWidget::dragEnterEvent(QDragEnterEvent *event)
  77.         {
  78.                 if (event->mimeData()->hasFormat("application/x-dnditemdata")) {
  79.                         if (event->source() == this) {
  80.                                 event->setDropAction(Qt::MoveAction);
  81.                                 event->accept();
  82.                         }
  83.                         else {
  84.                                 event->acceptProposedAction();
  85.                         }
  86.                 }
  87.                 else {
  88.                         event->ignore();
  89.                 }
  90.         }

  91.         bool OSGWidget::event(QEvent* event)
  92.         {
  93.                 bool handled = QGLWidget::event(event);
  94.                 // This ensures that the OSG widget is always going to be repainted after the
  95.                 // user performed some interaction. Doing this in the event handler ensures
  96.                 // that we don't forget about some event and prevents duplicate code.
  97.                 switch (event->type()) {
  98.                 case QEvent::KeyPress:
  99.                 case QEvent::KeyRelease:
  100.                 case QEvent::MouseButtonDblClick:
  101.                 case QEvent::MouseButtonPress:
  102.                 case QEvent::MouseButtonRelease:
  103.                 case QEvent::Wheel:
  104.                         this->update();
  105.                         break;
  106.                 default:
  107.                         break;
  108.                 }
  109.                 return(handled);
  110.         }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表